WGU D385 ZHN1 Task 2
Software Security and Testing
Secure Coding and Secure API Implementation
Western Governors University | 2026/2027
Course: D385 - Software Security and Testing
Assessment: ZHN1 Task 2
Report: Security Vulnerability Remediation and API Security Implementation
Technology: Python, Flask, REST APIs, pytest
Scope: This written report addresses the uploaded ZHN1 Task 2 instructions and accompanies an original, independently
developed Flask secure-API demonstration. The official WGU student-starter ZIP and its task_2_flake8_report.txt
and task_2_bandit_report.txt files were not provided. Consequently, the four examples, original-source line numbers,
and test screenshots cannot be represented as verified findings or evidence from that starter application.
Introduction
Application programming interfaces are essential components of modern software systems because they allow
applications to exchange information and access services. However, APIs can also introduce security
vulnerabilities when authentication, authorization, input validation, and sensitive information are not adequately
protected.
The purpose of this project is to examine a Python-based application, identify weaknesses in its security controls,
and implement appropriate mitigation measures. Particular attention is given to protecting application credentials,
preventing unauthorized access, enforcing role-based permissions, and validating the effectiveness of changes
through automated testing.
The assessment scenario involves an internal API that retrieves user information and communicates with a
backend service. The application has reportedly experienced unauthorized access attempts, suspicious inputs, and
deficiencies in authorization logic. The development team's responsibility is to strengthen the application's
security without unnecessarily disrupting its intended functionality.
This report addresses four security weaknesses through a combination of secure configuration management,
password hashing, API authentication, and role-based authorization. It also evaluates input validation, exception
handling, encryption, and the principles of least privilege and defense in depth.
Scope of the implementation
The WGU assessment specifies that two general vulnerabilities must be selected from
task_2_flake8_report.txt and two API vulnerabilities from task_2_bandit_report.txt. It also requires
the original and secured code, with the original vulnerable statements preserved as comments, and screenshots
demonstrating successful tests (Western Governors University [WGU], n.d.).
The starter application and its scanner reports were not included in the provided files. Therefore, this
implementation uses four relevant vulnerability categories as an independently developed worked example. Their
exact correspondence to WGU starter-code findings and original line numbers remains unverified.
WGU D385 ZHN1 Task 2 1
,WGU D385 ZHN1 Task 2
Identifier Vulnerability addressed Implemented security control
A-V1 Hardcoded security secrets External configuration and generated secret values
A-V2 Plaintext password storage Salted, adaptive password hashing
B-V1 Missing API authentication Bearer-token verification
B-V2 Broken API authorization Role-based access control and least privilege
These categories are consistent with the OWASP API Security Top 10 and recognized secure coding
recommendations. Broken object-level authorization and broken authentication are identified as major API
security risks (OWASP, 2023).
A. General Security Vulnerability Identification and Remediation
A1. Identification of Two General Security Vulnerabilities
A1.1. Vulnerability 1 - Hardcoded Application Secrets and Credentials
Hardcoded credentials occur when sensitive authentication information is embedded directly within an
application's source code. Examples include application secret keys, API keys, passwords, and database
authentication credentials. This practice creates security risks because source code may be copied, shared,
uploaded to repositories, or accessed by individuals who should not have access to production credentials.
If a secret is included directly in source code, any person with access to that file may be able to obtain the
credential. Furthermore, changing an exposed secret may require changes to the application's source, followed by
testing and redeployment. For Flask applications, a secret key is particularly important when signed session
information is used. An exposed signing key can undermine the integrity protection of affected session data.
The following is an illustrative example of the insecure coding pattern:
# Insecure example only; never enable
app.secret_key = "fixed-in-source-example-key"
The weakness is not that a secret key exists, but that its value is predictable or unnecessarily exposed through the
codebase. OWASP recommends managing application secrets through a suitable secrets management system, with
restricted access and procedures for credential rotation. Environment-based configuration can be used for a small
development project, although a dedicated secrets manager is preferable in production (OWASP, n.d.-c).
Potential security impact. A disclosed secret could enable unauthorized use of application functionality,
manipulation of signed data where applicable, or unauthorized access to connected systems. Exposed credentials
also complicate security incident response. If a secret appears in a public repository, developers may need to rotate
it, review related logs, and determine whether the credential was misused. The risk can be reduced by eliminating
fixed secrets from application source files and managing secret values independently of ordinary program logic.
WGU D385 ZHN1 Task 2 2
, WGU D385 ZHN1 Task 2
A1.2. Vulnerability 2 - Plaintext Password Storage
Plaintext password storage occurs when an application retains users' actual passwords in readable form rather than
using an appropriate one-way password hashing mechanism. A basic application might store user details in a
dictionary or database and compare a submitted password directly against a stored string.
# Insecure example only; never enable
users = {
"admin": {
"password": "plaintext-example",
"role": "admin"
}
}
This approach creates an unnecessary risk because anyone who obtains the user database or configuration
containing passwords can read those credentials immediately. It also increases the consequences if users reuse
credentials on other systems. A secure application should not retain recoverable plaintext passwords for routine
password authentication. Instead, it should store salted password hashes generated using an adaptive password
hashing algorithm. OWASP recommends algorithms such as Argon2id, scrypt, or appropriately configured
PBKDF2 rather than fast general-purpose hashing functions (OWASP, n.d.-a).
Potential security impact. Plaintext password storage threatens credential confidentiality and can contribute to
unauthorized account access. It undermines defense in depth because a single data disclosure can immediately
reveal reusable authentication material. Suitable password hashing reduces that risk by ensuring stored
representations cannot simply be read as the original passwords.
A2. Secure Remediation of the General Vulnerabilities
A2.1. Remediation of Hardcoded Secrets
The first mitigation replaces fixed application secrets with values supplied through external configuration. The
Flask application obtains its configured secret from an environment variable. When a development secret is not
supplied, the example can generate an unpredictable temporary secret using Python's secrets module.
import os
import secrets
app.secret_key = (
os.environ.get("D385_FLASK_SECRET_KEY")
or secrets.token_hex(32)
)
The secrets.token_hex(32) operation generates a cryptographically unpredictable value rather than relying on
a fixed string. For production deployments, a persistent secret must be provisioned through protected
configuration or a secret-management mechanism rather than regenerated on every application restart.
The secure API implementation also obtains API credentials from deployment configuration. These credentials are
not embedded as fixed values in production source code. The application stores cryptographic fingerprints of
high-entropy API keys for comparisons rather than retaining each raw API key in an application record. This
reduces the risk of exposing credentials from in-memory account structures and supports safer credential rotation.
Restricting access to the secret source remains necessary.
WGU D385 ZHN1 Task 2 3
Software Security and Testing
Secure Coding and Secure API Implementation
Western Governors University | 2026/2027
Course: D385 - Software Security and Testing
Assessment: ZHN1 Task 2
Report: Security Vulnerability Remediation and API Security Implementation
Technology: Python, Flask, REST APIs, pytest
Scope: This written report addresses the uploaded ZHN1 Task 2 instructions and accompanies an original, independently
developed Flask secure-API demonstration. The official WGU student-starter ZIP and its task_2_flake8_report.txt
and task_2_bandit_report.txt files were not provided. Consequently, the four examples, original-source line numbers,
and test screenshots cannot be represented as verified findings or evidence from that starter application.
Introduction
Application programming interfaces are essential components of modern software systems because they allow
applications to exchange information and access services. However, APIs can also introduce security
vulnerabilities when authentication, authorization, input validation, and sensitive information are not adequately
protected.
The purpose of this project is to examine a Python-based application, identify weaknesses in its security controls,
and implement appropriate mitigation measures. Particular attention is given to protecting application credentials,
preventing unauthorized access, enforcing role-based permissions, and validating the effectiveness of changes
through automated testing.
The assessment scenario involves an internal API that retrieves user information and communicates with a
backend service. The application has reportedly experienced unauthorized access attempts, suspicious inputs, and
deficiencies in authorization logic. The development team's responsibility is to strengthen the application's
security without unnecessarily disrupting its intended functionality.
This report addresses four security weaknesses through a combination of secure configuration management,
password hashing, API authentication, and role-based authorization. It also evaluates input validation, exception
handling, encryption, and the principles of least privilege and defense in depth.
Scope of the implementation
The WGU assessment specifies that two general vulnerabilities must be selected from
task_2_flake8_report.txt and two API vulnerabilities from task_2_bandit_report.txt. It also requires
the original and secured code, with the original vulnerable statements preserved as comments, and screenshots
demonstrating successful tests (Western Governors University [WGU], n.d.).
The starter application and its scanner reports were not included in the provided files. Therefore, this
implementation uses four relevant vulnerability categories as an independently developed worked example. Their
exact correspondence to WGU starter-code findings and original line numbers remains unverified.
WGU D385 ZHN1 Task 2 1
,WGU D385 ZHN1 Task 2
Identifier Vulnerability addressed Implemented security control
A-V1 Hardcoded security secrets External configuration and generated secret values
A-V2 Plaintext password storage Salted, adaptive password hashing
B-V1 Missing API authentication Bearer-token verification
B-V2 Broken API authorization Role-based access control and least privilege
These categories are consistent with the OWASP API Security Top 10 and recognized secure coding
recommendations. Broken object-level authorization and broken authentication are identified as major API
security risks (OWASP, 2023).
A. General Security Vulnerability Identification and Remediation
A1. Identification of Two General Security Vulnerabilities
A1.1. Vulnerability 1 - Hardcoded Application Secrets and Credentials
Hardcoded credentials occur when sensitive authentication information is embedded directly within an
application's source code. Examples include application secret keys, API keys, passwords, and database
authentication credentials. This practice creates security risks because source code may be copied, shared,
uploaded to repositories, or accessed by individuals who should not have access to production credentials.
If a secret is included directly in source code, any person with access to that file may be able to obtain the
credential. Furthermore, changing an exposed secret may require changes to the application's source, followed by
testing and redeployment. For Flask applications, a secret key is particularly important when signed session
information is used. An exposed signing key can undermine the integrity protection of affected session data.
The following is an illustrative example of the insecure coding pattern:
# Insecure example only; never enable
app.secret_key = "fixed-in-source-example-key"
The weakness is not that a secret key exists, but that its value is predictable or unnecessarily exposed through the
codebase. OWASP recommends managing application secrets through a suitable secrets management system, with
restricted access and procedures for credential rotation. Environment-based configuration can be used for a small
development project, although a dedicated secrets manager is preferable in production (OWASP, n.d.-c).
Potential security impact. A disclosed secret could enable unauthorized use of application functionality,
manipulation of signed data where applicable, or unauthorized access to connected systems. Exposed credentials
also complicate security incident response. If a secret appears in a public repository, developers may need to rotate
it, review related logs, and determine whether the credential was misused. The risk can be reduced by eliminating
fixed secrets from application source files and managing secret values independently of ordinary program logic.
WGU D385 ZHN1 Task 2 2
, WGU D385 ZHN1 Task 2
A1.2. Vulnerability 2 - Plaintext Password Storage
Plaintext password storage occurs when an application retains users' actual passwords in readable form rather than
using an appropriate one-way password hashing mechanism. A basic application might store user details in a
dictionary or database and compare a submitted password directly against a stored string.
# Insecure example only; never enable
users = {
"admin": {
"password": "plaintext-example",
"role": "admin"
}
}
This approach creates an unnecessary risk because anyone who obtains the user database or configuration
containing passwords can read those credentials immediately. It also increases the consequences if users reuse
credentials on other systems. A secure application should not retain recoverable plaintext passwords for routine
password authentication. Instead, it should store salted password hashes generated using an adaptive password
hashing algorithm. OWASP recommends algorithms such as Argon2id, scrypt, or appropriately configured
PBKDF2 rather than fast general-purpose hashing functions (OWASP, n.d.-a).
Potential security impact. Plaintext password storage threatens credential confidentiality and can contribute to
unauthorized account access. It undermines defense in depth because a single data disclosure can immediately
reveal reusable authentication material. Suitable password hashing reduces that risk by ensuring stored
representations cannot simply be read as the original passwords.
A2. Secure Remediation of the General Vulnerabilities
A2.1. Remediation of Hardcoded Secrets
The first mitigation replaces fixed application secrets with values supplied through external configuration. The
Flask application obtains its configured secret from an environment variable. When a development secret is not
supplied, the example can generate an unpredictable temporary secret using Python's secrets module.
import os
import secrets
app.secret_key = (
os.environ.get("D385_FLASK_SECRET_KEY")
or secrets.token_hex(32)
)
The secrets.token_hex(32) operation generates a cryptographically unpredictable value rather than relying on
a fixed string. For production deployments, a persistent secret must be provisioned through protected
configuration or a secret-management mechanism rather than regenerated on every application restart.
The secure API implementation also obtains API credentials from deployment configuration. These credentials are
not embedded as fixed values in production source code. The application stores cryptographic fingerprints of
high-entropy API keys for comparisons rather than retaining each raw API key in an application record. This
reduces the risk of exposing credentials from in-memory account structures and supports safer credential rotation.
Restricting access to the secret source remains necessary.
WGU D385 ZHN1 Task 2 3