Skip to content

Harden auth recovery flow and disable perpetual admin tokens by default#6

Merged
parkcheolhong merged 1 commit into
mainfrom
copilot/fix-security-issues
May 8, 2026
Merged

Harden auth recovery flow and disable perpetual admin tokens by default#6
parkcheolhong merged 1 commit into
mainfrom
copilot/fix-security-issues

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 8, 2026

The issue was in security-sensitive auth paths: password recovery accepted a predictable verification code and admin sessions could receive non-expiring tokens by default. This change tightens both flows without changing the public API surface.

  • Password recovery hardening

    • Replaces the fixed recovery verification code with a random 6-digit code.
    • Normalizes and validates allowed recovery scopes.
    • Expires stale in-memory recovery sessions before use.
  • Recovery abuse controls

    • Tracks failed verification attempts per recovery session.
    • Invalidates the session after the configured attempt limit.
    • Requires completed identity verification before accepting a reset token.
  • Admin token policy

    • Stops issuing non-expiring admin tokens unless explicitly enabled via environment configuration.
    • Keeps existing admin behavior opt-in rather than default.
  • Regression coverage

    • Adds focused tests for:
      • default-expiring admin tokens
      • randomized recovery codes
      • retry limit enforcement
      • reset rejection before identity verification
      • successful reset path after verification
def _should_issue_non_expiring_admin_token(user: User) -> bool:
    allow_non_expiring_admin_tokens = (
        str(os.getenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS") or "").strip().lower()
        in {"1", "true", "yes", "on"}
    )
    return allow_non_expiring_admin_tokens and bool(
        getattr(user, "is_admin", False)
        or getattr(user, "is_superuser", False)
    )

Summary by Sourcery

Harden password recovery and admin token issuance security behavior without changing the public API.

New Features:

  • Introduce configurable limits on password recovery verification attempts with automatic invalidation of abused sessions.

Bug Fixes:

  • Prevent issuance of non-expiring admin tokens by default, requiring explicit environment configuration to enable them.

Enhancements:

  • Generate random verification codes for password recovery instead of using a fixed value.
  • Normalize and validate allowed password recovery scopes and purge expired in-memory recovery sessions before use.
  • Require successful identity verification before allowing password reset via recovery and use constant-time comparisons for codes and reset tokens.

Tests:

  • Add focused tests covering admin token expiry defaults, randomized recovery codes, verification retry limits, mandatory identity verification, and successful password reset behavior.

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/3d52b2c5-9c5a-43f7-91a5-9587bc9ce9a5

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>
@parkcheolhong parkcheolhong marked this pull request as ready for review May 8, 2026 09:35
Copilot AI review requested due to automatic review settings May 8, 2026 09:35
@parkcheolhong parkcheolhong merged commit 5b48abe into main May 8, 2026
3 checks passed
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented May 8, 2026

Reviewer's Guide

Tightens security around password recovery and admin token issuance by introducing randomized verification codes, scope normalization/validation, session purging and abuse controls for recovery flows, and making non-expiring admin tokens opt-in via environment configuration, backed by focused tests.

Sequence diagram for hardened password recovery flow

sequenceDiagram
    actor User
    participant AuthRouter
    participant PasswordRecoveryStore

    User->>AuthRouter: POST /recovery/start (user_hint, scope)
    AuthRouter->>AuthRouter: _purge_expired_password_recovery_sessions
    AuthRouter->>AuthRouter: _normalize_password_recovery_scope
    AuthRouter->>PasswordRecoveryStore: Create recovery_session
    Note over PasswordRecoveryStore: Store user_id, scope, verified=false,
    Note over PasswordRecoveryStore: verification_code=random_6_digits,
    Note over PasswordRecoveryStore: verification_attempts=0, expires_at

    User->>AuthRouter: POST /recovery/verify-identity
    AuthRouter->>AuthRouter: _purge_expired_password_recovery_sessions
    AuthRouter->>PasswordRecoveryStore: Load recovery_session
    AuthRouter->>AuthRouter: Check expires_at
    alt session_expired_or_missing
        AuthRouter-->>User: 404 or 410 error
    else session_ok
        AuthRouter->>AuthRouter: compare_digest(input_code, expected_code)
        alt code_mismatch
            AuthRouter->>PasswordRecoveryStore: Increment verification_attempts
            alt attempts_exceeded
                AuthRouter->>PasswordRecoveryStore: Delete recovery_session
                AuthRouter-->>User: 429 too many attempts
            else attempts_remaining
                AuthRouter-->>User: 401 invalid code
            end
        else code_match
            AuthRouter->>AuthRouter: _issue_recovery_token for reset
            AuthRouter->>PasswordRecoveryStore: Set verified=true
            AuthRouter->>PasswordRecoveryStore: Store identity_session_token
            AuthRouter->>PasswordRecoveryStore: Store reset_token, reset_expires_at
            AuthRouter->>PasswordRecoveryStore: Reset verification_attempts=0
            AuthRouter-->>User: recovery_session_token, reset_token
        end
    end

    User->>AuthRouter: POST /recovery/reset-password
    AuthRouter->>AuthRouter: _purge_expired_password_recovery_sessions
    AuthRouter->>AuthRouter: Validate new_password length
    AuthRouter->>AuthRouter: _normalize_password_recovery_scope
    AuthRouter->>PasswordRecoveryStore: Find session by scope and compare_digest(reset_token)
    alt no_matching_session
        AuthRouter-->>User: 404 reset token not found
    else session_found
        AuthRouter->>AuthRouter: Check verified and identity_session_token
        alt not_verified_or_missing_identity
            AuthRouter-->>User: 403 identity verification incomplete
        else verified
            AuthRouter->>AuthRouter: Check reset_expires_at
            alt reset_token_expired
                AuthRouter->>PasswordRecoveryStore: Delete recovery_session
                AuthRouter-->>User: 410 reset token expired
            else reset_token_valid
                AuthRouter->>AuthRouter: Update user password
                AuthRouter->>PasswordRecoveryStore: Delete recovery_session
                AuthRouter-->>User: 200 password reset success
            end
        end
    end
Loading

Flow diagram for password recovery session lifecycle and abuse controls

flowchart TD
    A["Start password recovery request"] --> B["_purge_expired_password_recovery_sessions"]
    B --> C["Normalize and validate scope (admin or user)"]
    C --> D["Lookup user by email or username"]
    D -->|not found| E["404 no matching account"]
    D -->|found| F{"Scope admin and user not admin/superuser?"}
    F -->|yes| G["403 admin-only recovery path"]
    F -->|no| H["Create recovery session in store\nverification_code=random 6 digits\nverification_attempts=0\nverified=false"]
    H --> I["Send verification code to user"]

    subgraph Identity verification
        I --> J["User submits verification code"]
        J --> K["_purge_expired_password_recovery_sessions"]
        K --> L{"Recovery session exists and not expired?"}
        L -->|no| M["404 or 410 session error"]
        L -->|yes| N{"compare_digest(input_code, stored_code)"}
        N -->|mismatch| O["Increment verification_attempts"]
        O --> P{"attempts >= PASSWORD_RECOVERY_MAX_VERIFY_ATTEMPTS?"}
        P -->|yes| Q["Delete session and return 429 too many attempts"]
        P -->|no| R["Return 401 invalid code"]
        N -->|match| S["Mark verified=true, reset verification_attempts=0\nissue reset_token and reset_expires_at\nstore identity_session_token"]
    end

    S --> T["User submits reset password request"]

    subgraph Password reset
        T --> U["_purge_expired_password_recovery_sessions"]
        U --> V["Validate new_password length >= 8"]
        V -->|invalid| W["400 weak password"]
        V -->|valid| X["Normalize and validate scope"]
        X --> Y["Find session with matching scope\nand compare_digest(reset_token)"]
        Y -->|not found| Z["404 reset token not found"]
        Y -->|found| AA{"verified is true and identity_session_token present?"}
        AA -->|no| AB["403 identity verification incomplete"]
        AA -->|yes| AC{"reset_expires_at > now?"}
        AC -->|no| AD["Delete session and return 410 reset token expired"]
        AC -->|yes| AE["Update user password"]
        AE --> AF["Delete recovery session from store"]
        AF --> AG["Return 200 password reset success"]
    end
Loading

File-Level Changes

Change Details Files
Make non-expiring admin tokens opt-in via environment variable.
  • Add ALLOW_NON_EXPIRING_ADMIN_TOKENS env flag parsing with normalized truthy values
  • Gate non-expiring admin token issuance on both the env flag and admin/superuser status
  • Add tests verifying default-expiring admin tokens and opt-in behavior when the flag is set
backend/auth_router.py
tests/test_auth_router_security.py
Harden password recovery start flow with scope validation, randomized codes, and session purging.
  • Introduce allowed recovery scopes constant and normalization helper that validates scope and raises on unsupported values
  • Replace fixed password recovery verification code with a random 6-digit code generator
  • Purge expired password recovery sessions before starting a new recovery and when handling recovery endpoints
  • Extend stored recovery session state with scope, random verification_code, attempts counter, and expiry metadata
  • Add tests to verify randomized verification codes and correct session state initialization
backend/auth_router.py
tests/test_auth_router_security.py
Add abuse controls and stricter verification for identity verification step in recovery.
  • Track verification_attempts per recovery session and enforce a configurable max attempts from PASSWORD_RECOVERY_MAX_VERIFY_ATTEMPTS env var
  • Use constant-time compare_digest when checking verification codes
  • Invalidate recovery session and return HTTP 429 when attempts exceed the limit; keep 401 for intermediate failures
  • Reset verification_attempts on successful verification and persist identity_session_token/reset_token with expirations
  • Add tests to assert attempt limiting behavior and HTTP status codes
backend/auth_router.py
tests/test_auth_router_security.py
Enforce verified identity and secure token comparison in password reset flow.
  • Normalize and validate scope for reset requests using the same helper as start flow
  • Match sessions using constant-time comparison for reset_token plus validated scope
  • Require verified identity and a non-empty identity_session_token before accepting a password reset, returning 403 otherwise
  • Ensure expired reset tokens purge the session and reject the request; on success, update hashed_password, commit, and clear the session
  • Add tests confirming reset requires verified identity and that a successful reset updates the hash, commits, and clears the session
backend/auth_router.py
tests/test_auth_router_security.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@parkcheolhong
Copy link
Copy Markdown
Owner

수고했습니다, 부조종사님

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 8 issues, and left some high level feedback:

  • The _should_issue_non_expiring_admin_token helper re-parses the ALLOW_NON_EXPIRING_ADMIN_TOKENS environment variable on every call; consider reading this once into a config or module-level flag to avoid repeated env/string work on hot paths.
  • Both _purge_expired_password_recovery_sessions and reset_password_via_recovery iterate linearly over _password_recovery_store; if this store can grow, consider indexing sessions by reset token (and/or expiry) to avoid O(n) scans on every recovery-related request.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `_should_issue_non_expiring_admin_token` helper re-parses the `ALLOW_NON_EXPIRING_ADMIN_TOKENS` environment variable on every call; consider reading this once into a config or module-level flag to avoid repeated env/string work on hot paths.
- Both `_purge_expired_password_recovery_sessions` and `reset_password_via_recovery` iterate linearly over `_password_recovery_store`; if this store can grow, consider indexing sessions by reset token (and/or expiry) to avoid O(n) scans on every recovery-related request.

## Individual Comments

### Comment 1
<location path="backend/auth_router.py" line_range="265-266" />
<code_context>
+    return f"{randbelow(1_000_000):06d}"
+
+
+def _normalize_password_recovery_scope(scope: str) -> str:
+    normalized = str(scope or "admin").strip().lower()
+    if normalized not in _PASSWORD_RECOVERY_ALLOWED_SCOPES:
+        raise HTTPException(
</code_context>
<issue_to_address>
**🚨 issue (security):** Defaulting a falsy scope to 'admin' is risky and may accidentally elevate recovery privileges.

`scope or "admin"` makes any falsy or empty scope (e.g. missing field, empty string) behave as an admin recovery request, so validation failures can silently become admin flows. Consider either defaulting to a non-privileged scope like `"user"` or requiring a non-empty scope and raising if it’s falsy.
</issue_to_address>

### Comment 2
<location path="backend/auth_router.py" line_range="626-628" />
<code_context>
     matched_session = None
     for session_token, session_state in _password_recovery_store.items():
-        if session_state.get("reset_token") == payload.reset_token and session_state.get("scope") == payload.scope:
+        if (
+            session_state.get("scope") == scope
+            and compare_digest(str(session_state.get("reset_token") or ""), payload.reset_token)
+        ):
             matched_session = (session_token, session_state)
</code_context>
<issue_to_address>
**suggestion:** Consider normalizing the incoming reset token before constant-time comparison to reduce UX friction.

`payload.reset_token` is compared verbatim to a normalized session token. If the client sends the correct token with extra whitespace (e.g. from copy‑paste), `compare_digest` will fail. Trimming or otherwise normalizing `payload.reset_token` (for example, `payload.reset_token.strip()`) before comparison would handle these cases without affecting security.

Suggested implementation:

```python
    scope = _normalize_password_recovery_scope(payload.scope)
    normalized_reset_token = (payload.reset_token or "").strip()
    matched_session = None
    for session_token, session_state in _password_recovery_store.items():

```

```python
        if (
            session_state.get("scope") == scope
            and compare_digest(str(session_state.get("reset_token") or ""), normalized_reset_token)
        ):

```
</issue_to_address>

### Comment 3
<location path="tests/test_auth_router_security.py" line_range="58-67" />
<code_context>
+    return importlib.import_module("backend.auth_router")
+
+
+def test_admin_tokens_expire_by_default(monkeypatch):
+    monkeypatch.delenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", raising=False)
+    auth_router = _load_auth_router(monkeypatch)
+    admin_user = SimpleNamespace(is_admin=True, is_superuser=False)
+
+    assert auth_router._should_issue_non_expiring_admin_token(admin_user) is False
+
+    monkeypatch.setenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", "true")
+    auth_router = _load_auth_router(monkeypatch)
+    assert auth_router._should_issue_non_expiring_admin_token(admin_user) is True
+
+
</code_context>
<issue_to_address>
**suggestion (testing):** Add parametrized tests for all supported ALLOW_NON_EXPIRING_ADMIN_TOKENS values and non-admin users

This test only covers the default and a single truthy value. Since `_should_issue_non_expiring_admin_token` accepts multiple truthy strings and depends on admin/superuser flags, please parameterize it to cover:

- All accepted truthy values (e.g. `"1"`, `"true"`, `"yes"`, `"on"`, plus casing/whitespace variants) returning `True` for an admin user.
- A non-admin user returning `False` even when the env var is a truthy value.
- Falsy/invalid values (e.g. `"false"`, `"0"`, `"random"`) returning `False` for an admin user.

This will better guard against regressions and ensure the env flag semantics remain consistent.

Suggested implementation:

```python
import pytest
from fastapi import HTTPException
from types import SimpleNamespace

```

```python
@pytest.mark.parametrize(
    "env_value",
    [
        "1",
        "true",
        "yes",
        "on",
        "TRUE",
        "Yes",
        "On",
        "  true  ",
    ],
)
def test_should_issue_non_expiring_admin_token_for_truthy_values(monkeypatch, env_value):
    monkeypatch.setenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", env_value)
    auth_router = _load_auth_router(monkeypatch)
    admin_user = SimpleNamespace(is_admin=True, is_superuser=False)

    assert auth_router._should_issue_non_expiring_admin_token(admin_user) is True


@pytest.mark.parametrize(
    "env_value",
    [
        None,  # unset / default
        "",
        "false",
        "0",
        "no",
        "off",
        "FALSE",
        "No",
        "Off",
        "random",
        "  ",
    ],
)
def test_should_not_issue_non_expiring_admin_token_for_falsy_or_invalid_values(
    monkeypatch, env_value
):
    if env_value is None:
        monkeypatch.delenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", raising=False)
    else:
        monkeypatch.setenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", env_value)

    auth_router = _load_auth_router(monkeypatch)
    admin_user = SimpleNamespace(is_admin=True, is_superuser=False)

    assert auth_router._should_issue_non_expiring_admin_token(admin_user) is False


@pytest.mark.parametrize(
    "env_value",
    [
        "1",
        "true",
        "yes",
        "on",
        "TRUE",
        "Yes",
        "On",
        "  true  ",
    ],
)
def test_should_not_issue_non_expiring_token_for_non_admin_users(monkeypatch, env_value):
    monkeypatch.setenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", env_value)
    auth_router = _load_auth_router(monkeypatch)
    non_admin_user = SimpleNamespace(is_admin=False, is_superuser=False)

    assert auth_router._should_issue_non_expiring_admin_token(non_admin_user) is False

```
</issue_to_address>

### Comment 4
<location path="tests/test_auth_router_security.py" line_range="70-86" />
<code_context>
+    assert auth_router._should_issue_non_expiring_admin_token(admin_user) is True
+
+
+def test_start_password_recovery_uses_random_verification_code(monkeypatch):
+    auth_router = _load_auth_router(monkeypatch)
+    auth_router._password_recovery_store.clear()
+    monkeypatch.setattr(auth_router, "randbelow", lambda upper_bound: 123456)
+    db = _FakeDB(SimpleNamespace(id=7, is_admin=True, is_superuser=False))
+
+    response = auth_router.start_password_recovery(
+        auth_router.PasswordRecoveryStartRequest(
+            scope="admin",
+            user_hint="admin@example.com",
+        ),
+        db,
+    )
+
+    session_state = auth_router._password_recovery_store[response["recovery_session_token"]]
+    assert session_state["verification_code"] == "123456"
+    assert session_state["verification_code"] != "000000"
+
+
</code_context>
<issue_to_address>
**suggestion (testing):** Cover zero-padding and multi-session behavior of the recovery verification code

To strengthen this test, consider adding:

- Zero-padding: monkeypatch `randbelow` to return a small value (e.g. `42`) and assert `verification_code == "000042"` to cover the formatting logic.
- Multi-session uniqueness: create two sessions in sequence with different `randbelow` outputs and assert their verification codes differ, confirming per-session randomness.

These can be added via parametrization or as a dedicated padding/uniqueness test.

```suggestion
def test_start_password_recovery_uses_random_verification_code(monkeypatch):
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    monkeypatch.setattr(auth_router, "randbelow", lambda upper_bound: 123456)
    db = _FakeDB(SimpleNamespace(id=7, is_admin=True, is_superuser=False))

    response = auth_router.start_password_recovery(
        auth_router.PasswordRecoveryStartRequest(
            scope="admin",
            user_hint="admin@example.com",
        ),
        db,
    )

    session_state = auth_router._password_recovery_store[response["recovery_session_token"]]
    assert session_state["verification_code"] == "123456"
    assert session_state["verification_code"] != "000000"


def test_start_password_recovery_zero_pads_verification_code(monkeypatch):
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    # Force a small random value to exercise zero-padding logic
    monkeypatch.setattr(auth_router, "randbelow", lambda upper_bound: 42)
    db = _FakeDB(SimpleNamespace(id=7, is_admin=True, is_superuser=False))

    response = auth_router.start_password_recovery(
        auth_router.PasswordRecoveryStartRequest(
            scope="admin",
            user_hint="admin@example.com",
        ),
        db,
    )

    session_state = auth_router._password_recovery_store[response["recovery_session_token"]]
    assert session_state["verification_code"] == "000042"


def test_start_password_recovery_generates_unique_codes_per_session(monkeypatch):
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()

    # Simulate different random outputs for consecutive sessions
    random_values = iter([123456, 654321])

    def _fake_randbelow(upper_bound):
        return next(random_values)

    monkeypatch.setattr(auth_router, "randbelow", _fake_randbelow)
    db = _FakeDB(SimpleNamespace(id=7, is_admin=True, is_superuser=False))

    response1 = auth_router.start_password_recovery(
        auth_router.PasswordRecoveryStartRequest(
            scope="admin",
            user_hint="admin1@example.com",
        ),
        db,
    )
    response2 = auth_router.start_password_recovery(
        auth_router.PasswordRecoveryStartRequest(
            scope="admin",
            user_hint="admin2@example.com",
        ),
        db,
    )

    session_state1 = auth_router._password_recovery_store[response1["recovery_session_token"]]
    session_state2 = auth_router._password_recovery_store[response2["recovery_session_token"]]

    assert session_state1["verification_code"] == "123456"
    assert session_state2["verification_code"] == "654321"
    assert session_state1["verification_code"] != session_state2["verification_code"]
```
</issue_to_address>

### Comment 5
<location path="tests/test_auth_router_security.py" line_range="89-98" />
<code_context>
+def test_password_recovery_verify_identity_limits_failed_attempts(monkeypatch):
</code_context>
<issue_to_address>
**suggestion (testing):** Add a positive-path test for identity verification, including reset of attempt counter and reset-token issuance

This test covers the failure path and 401/429 behavior well. To fully cover `verify_password_recovery_identity`, please also add a positive-path test that:

- Begins with a session where `verification_attempts` > 0,
- Submits a correct `verification_code`,
- Asserts that:
  - `session_state["verified"]` becomes `True`,
  - `session_state["verification_attempts"]` is reset to `0`,
  - `identity_session_token`, `reset_token`, and `reset_expires_at` are correctly set,
  - The response exposes a usable `reset_token`.

This will guard against regressions in the successful verification flow while enforcing the attempt limit.

Suggested implementation:

```python
def test_password_recovery_verify_identity_limits_failed_attempts(monkeypatch):


def test_password_recovery_verify_identity_success_resets_attempts_and_issues_reset_token(monkeypatch, db):
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()

    recovery_session_token = "recovery_test_success"
    auth_router._password_recovery_store[recovery_session_token] = {
        "user_id": 1,
        "scope": "admin",
        "verified": False,
        "verification_code": "654321",
        "verification_attempts": 2,
        "expires_at": datetime.utcnow() + timedelta(minutes=5),
    }

    response = auth_router.verify_password_recovery_identity(
        recovery_session_token=recovery_session_token,
        verification_code="654321",
        db=db,
    )

    session_state = auth_router._password_recovery_store[recovery_session_token]

    # verification flag should be set
    assert session_state["verified"] is True
    # attempts counter should be reset
    assert session_state["verification_attempts"] == 0

    # reset / identity session fields should be issued
    assert "identity_session_token" in session_state
    assert "reset_token" in session_state
    assert "reset_expires_at" in session_state

    # response should expose usable reset_token
    assert response["reset_token"] == session_state["reset_token"]

```

To wire this in cleanly you may need to:

1. Confirm the verification entry point and adapt the call accordingly:
   - If the API is different (e.g. `verify_password_recovery_identity(db, recovery_session_token, verification_code)` or an HTTP route tested via a test client), adjust the `response = ...` line to use the actual call pattern and access the returned JSON body appropriately.
2. Ensure that the `db` fixture is available in this test module (other tests in the file likely already use it; if not, add or import it).
3. Place this new test at top-level (same indentation as other tests) and immediately after the existing `test_password_recovery_verify_identity_limits_failed_attempts` so both success and failure paths live together.
4. If your implementation uses different session-state keys (e.g. `"identity_session_token"` vs `"password_recovery_session_token"`), update the asserted keys to match the actual implementation.
</issue_to_address>

### Comment 6
<location path="tests/test_auth_router_security.py" line_range="118-127" />
<code_context>
+def test_reset_password_requires_verified_identity(monkeypatch):
</code_context>
<issue_to_address>
**suggestion (testing):** Distinguish between unverified and missing identity session token in reset-password tests

This test covers the `verified=False` → 403 behavior. The implementation also requires a non-empty `identity_session_token`. Please add a case where `verified=True` but `identity_session_token` is empty/whitespace or missing, and a reset with a valid `reset_token` still returns 403. That will exercise the identity proof requirement and help catch regressions where the token is ignored once `verified` is true.

Suggested implementation:

```python
def test_reset_password_requires_verified_identity(monkeypatch):
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()

    # Case 1: identity not verified → reset must be forbidden even with a valid reset token
    auth_router._password_recovery_store["recovery_test"] = {
        "user_id": 1,
        "scope": "admin",
        "verified": False,
        "reset_token": "reset_token",
        "reset_expires_at": datetime.utcnow() + timedelta(minutes=5),
        "expires_at": datetime.utcnow() + timedelta(minutes=5),
    }

    with pytest.raises(HTTPException) as exc_info:
        # use whatever helper/reset endpoint is used elsewhere in this file
        auth_router.reset_password(
            recovery_session_token="recovery_test",
            reset_token="reset_token",
            new_password="new-password-1",
        )
    assert exc_info.value.status_code == 403

    # Case 2: identity marked verified but missing/blank identity_session_token → still forbidden
    auth_router._password_recovery_store["recovery_test"] = {
        "user_id": 1,
        "scope": "admin",
        "verified": True,
        # intentionally omit or blank out identity_session_token to simulate missing proof
        "identity_session_token": "   ",
        "reset_token": "reset_token",
        "reset_expires_at": datetime.utcnow() + timedelta(minutes=5),
        "expires_at": datetime.utcnow() + timedelta(minutes=5),
    }

    with pytest.raises(HTTPException) as exc_info:
        auth_router.reset_password(
            recovery_session_token="recovery_test",
            reset_token="reset_token",
            new_password="new-password-2",
        )
    assert exc_info.value.status_code == 403

```

1. Replace `auth_router.reset_password(...)` with the actual function/route helper used elsewhere in this test file to perform a password reset, matching its parameter names and call style (e.g. using `client.post("/reset-password", json=...)` or similar).
2. Align the payload keys (`recovery_session_token`, `reset_token`, `new_password`) with your actual reset handler signature.
3. If the real implementation distinguishes between “missing” and “blank” `identity_session_token`, you may also want to add a third subcase where the key is completely omitted from the store entry.
</issue_to_address>

### Comment 7
<location path="tests/test_auth_router_security.py" line_range="143-152" />
<code_context>
+def test_reset_password_updates_hash_and_clears_session(monkeypatch):
</code_context>
<issue_to_address>
**suggestion (testing):** Add tests for scope normalization and invalid scopes in the recovery flow

The current test only covers the happy path for an `admin` scope, but the implementation now normalizes and validates scopes in both `start_password_recovery` and `reset_password_via_recovery`. Please add tests that:

- Use mixed-case and whitespace scopes (e.g. `"  Admin  "`, `"USER"`) for both start and reset, asserting that recovery succeeds, confirming consistent normalization.
- Use invalid scopes (e.g. `"root"`, `"foobar"`) for both start and reset, asserting a 400 and the expected error message.

This will ensure the allowed-scope guardrail is properly enforced and cannot be bypassed via casing or whitespace.

Suggested implementation:

```python
def test_reset_password_updates_hash_and_clears_session(monkeypatch):
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    user = SimpleNamespace(id=1, hashed_password="old")
    db = _FakeDB(user)

    # Seed a verified recovery entry for the user
    auth_router._password_recovery_store["recovery_test"] = {
        "user_id": 1,
        "scope": "admin",
        "verified": True,
        "identity_session_token": "identity-proof",
        "reset_token": "reset_token",
    }

    # Perform the reset
    auth_router.reset_password_via_recovery(
        SimpleNamespace(
            scope="admin",
            reset_token="reset_token",
            new_password="new-password-123",
        ),
        db,
    )

    # Password hash must change and recovery entry must be removed
    assert user.hashed_password != "old"
    assert "recovery_test" not in auth_router._password_recovery_store


def test_start_password_recovery_normalizes_scope(monkeypatch):
    """start_password_recovery should accept mixed-case/whitespace scopes."""
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    user = SimpleNamespace(id=1, email="user@example.com", hashed_password="old")
    db = _FakeDB(user)

    # Use mixed-case and whitespace for scope
    request = SimpleNamespace(
        email="user@example.com",
        scope="  Admin  ",
    )

    auth_router.start_password_recovery(request, db)

    # Recovery entry should exist and have normalized scope (e.g. 'admin')
    assert len(auth_router._password_recovery_store) == 1
    recovery = next(iter(auth_router._password_recovery_store.values()))
    assert recovery["user_id"] == user.id
    assert recovery["scope"] == "admin"


def test_start_password_recovery_rejects_invalid_scope(monkeypatch):
    """start_password_recovery should reject invalid scopes."""
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    user = SimpleNamespace(id=1, email="user@example.com", hashed_password="old")
    db = _FakeDB(user)

    for invalid_scope in ["root", "foobar"]:
        request = SimpleNamespace(
            email="user@example.com",
            scope=invalid_scope,
        )

        with pytest.raises(HTTPException) as exc_info:
            auth_router.start_password_recovery(request, db)

        assert exc_info.value.status_code == 400
        # The implementation should expose a clear invalid-scope error message
        assert "invalid scope" in exc_info.value.detail.lower()


def test_reset_password_via_recovery_normalizes_scope(monkeypatch):
    """reset_password_via_recovery should accept mixed-case/whitespace scopes."""
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    user = SimpleNamespace(id=1, hashed_password="old")
    db = _FakeDB(user)

    # Seed a verified recovery entry with normalized scope
    auth_router._password_recovery_store["recovery_test"] = {
        "user_id": 1,
        "scope": "admin",
        "verified": True,
        "identity_session_token": "identity-proof",
        "reset_token": "reset_token",
    }

    # Call reset with mixed-case and extra whitespace in scope
    auth_router.reset_password_via_recovery(
        SimpleNamespace(
            scope="  Admin  ",
            reset_token="reset_token",
            new_password="new-password-123",
        ),
        db,
    )

    # Ensure the reset still succeeds (hash changes and entry cleared)
    assert user.hashed_password != "old"
    assert "recovery_test" not in auth_router._password_recovery_store


def test_reset_password_via_recovery_rejects_invalid_scope(monkeypatch):
    """reset_password_via_recovery should reject invalid scopes."""
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    user = SimpleNamespace(id=1, hashed_password="old")
    db = _FakeDB(user)

    # Seed a verified recovery entry with an allowed scope
    auth_router._password_recovery_store["recovery_test"] = {
        "user_id": 1,
        "scope": "admin",
        "verified": True,
        "identity_session_token": "identity-proof",
        "reset_token": "reset_token",
    }

    for invalid_scope in ["root", "foobar"]:
        with pytest.raises(HTTPException) as exc_info:
            auth_router.reset_password_via_recovery(
                SimpleNamespace(
                    scope=invalid_scope,
                    reset_token="reset_token",
                    new_password="new-password-123",
                ),
                db,
            )

        assert exc_info.value.status_code == 400
        assert "invalid scope" in exc_info.value.detail.lower()

```

The above tests assume the following, based on typical patterns in this file:

1. `start_password_recovery(request, db)` accepts a `request` object with `email` and `scope` attributes and raises `HTTPException` on invalid scope, with a message that includes "invalid scope".
2. `reset_password_via_recovery(request, db)` will:
   - Normalize the `scope` from the request (trimming whitespace and normalizing case) and compare it against allowed scopes.
   - Raise `HTTPException(status_code=400, detail="...invalid scope...")` when the scope is invalid.
3. `auth_router._password_recovery_store` is a dict keyed by token with values containing at least `user_id`, `scope`, `verified`, `identity_session_token`, and `reset_token`.

If your actual request/DB interfaces or error messages differ, adjust:
- The `SimpleNamespace` fields used to construct the `request` objects.
- The error-message substring checks (`"invalid scope"`).
- Any additional assertions you want (e.g., checking that the identity session is cleared) to match your implementation.
</issue_to_address>

### Comment 8
<location path="tests/test_auth_router_security.py" line_range="38-47" />
<code_context>
+        self.committed = True
+
+
+def _load_auth_router(monkeypatch):
+    sys.modules.pop("backend.auth_router", None)
+
+    fake_database = types.ModuleType("backend.database")
+    fake_database.get_db = lambda: None
+
+    fake_models = types.ModuleType("backend.models")
+
+    class _StubUser:
+        id = "id"
+        email = "email"
+        username = "username"
+
+    fake_models.User = _StubUser
+
+    monkeypatch.setitem(sys.modules, "backend.database", fake_database)
+    monkeypatch.setitem(sys.modules, "backend.models", fake_models)
+    return importlib.import_module("backend.auth_router")
+
+
</code_context>
<issue_to_address>
**suggestion (testing):** Add coverage for purging expired password recovery sessions before start/verify/reset

Since `_purge_expired_password_recovery_sessions` is now invoked by all three recovery endpoints, it’d be helpful to add tests that:

- Populate `_password_recovery_store` with both an expired and a valid session.
- Invoke `start_password_recovery`, `verify_password_recovery_identity`, or `reset_password_via_recovery`.
- Assert that the expired session is removed and the endpoint response reflects the expiry (e.g. 404/410), while valid sessions still succeed.

This will keep the purge behavior verified as part of the recovery flow.

Suggested implementation:

```python
import datetime

import pytest
from fastapi import HTTPException

```

```python
class _FakeQuery:
    def __init__(self, user):
        self._user = user

    def filter(self, *args, **kwargs):
        return self


def _make_recovery_session(user_id: str, expires_at: datetime.datetime) -> dict:
    return {
        "user_id": user_id,
        "expires_at": expires_at,
    }


def test_start_password_recovery_purges_expired_sessions(monkeypatch):
    """
    When start_password_recovery is called, expired sessions should be purged
    while valid sessions remain usable.
    """
    auth_router = _load_auth_router(monkeypatch)

    store = auth_router._password_recovery_store
    store.clear()

    now = datetime.datetime.utcnow()
    expired_token = "expired-token"
    valid_token = "valid-token"

    store[expired_token] = _make_recovery_session("id", now - datetime.timedelta(minutes=5))
    store[valid_token] = _make_recovery_session("id", now + datetime.timedelta(minutes=5))

    # Calling the endpoint should purge expired sessions.
    # We expect the call path for an expired recovery flow to ultimately raise HTTPException.
    with pytest.raises(HTTPException) as excinfo:
        # The exact call signature may vary (e.g. a Pydantic model instead of a bare email),
        # but the point is to exercise the start_password_recovery flow.
        auth_router.start_password_recovery(email="email")

    assert excinfo.value.status_code in (404, 410)
    assert expired_token not in store
    assert valid_token in store


def test_verify_password_recovery_identity_purges_expired_sessions(monkeypatch):
    """
    When verify_password_recovery_identity is called, it should purge expired
    sessions and fail for expired tokens while still succeeding for valid tokens.
    """
    auth_router = _load_auth_router(monkeypatch)

    store = auth_router._password_recovery_store
    store.clear()

    now = datetime.datetime.utcnow()
    expired_token = "expired-token"
    valid_token = "valid-token"

    store[expired_token] = _make_recovery_session("id", now - datetime.timedelta(minutes=5))
    store[valid_token] = _make_recovery_session("id", now + datetime.timedelta(minutes=5))

    # Expired token should cause an HTTPException and be removed from the store.
    with pytest.raises(HTTPException) as excinfo:
        auth_router.verify_password_recovery_identity(token=expired_token)

    assert excinfo.value.status_code in (404, 410)
    assert expired_token not in store

    # Valid token should still succeed and remain in the store (or transition to the next state)
    auth_router.verify_password_recovery_identity(token=valid_token)
    assert valid_token in store or valid_token not in store  # allow for flows that consume the token


def test_reset_password_via_recovery_purges_expired_sessions(monkeypatch):
    """
    When reset_password_via_recovery is called, it should purge expired
    sessions and reject resets for expired tokens, while still allowing
    resets with valid tokens.
    """
    auth_router = _load_auth_router(monkeypatch)

    store = auth_router._password_recovery_store
    store.clear()

    now = datetime.datetime.utcnow()
    expired_token = "expired-token"
    valid_token = "valid-token"

    store[expired_token] = _make_recovery_session("id", now - datetime.timedelta(minutes=5))
    store[valid_token] = _make_recovery_session("id", now + datetime.timedelta(minutes=5))

    # Expired token reset attempt should fail and purge the expired session.
    with pytest.raises(HTTPException) as excinfo:
        auth_router.reset_password_via_recovery(
            token=expired_token,
            new_password="new-password",
        )

    assert excinfo.value.status_code in (404, 410)
    assert expired_token not in store

    # Valid token reset attempt should succeed.
    auth_router.reset_password_via_recovery(
        token=valid_token,
        new_password="new-password",
    )
    # Depending on implementation, the token may be consumed; the important
    # behavior here is that no exception is raised and the expired token is gone.

```

The above tests assume:
1. `backend.auth_router` exposes:
   - `_password_recovery_store` as a mutable mapping from token to a dict containing at least `user_id` and `expires_at: datetime`.
   - Functions `start_password_recovery`, `verify_password_recovery_identity`, and `reset_password_via_recovery` callable as shown.
2. `start_password_recovery` accepts an `email` keyword argument; if it instead expects a Pydantic model or different parameters, adjust the call to match.
3. `verify_password_recovery_identity` and `reset_password_via_recovery` accept a `token` parameter, and `reset_password_via_recovery` accepts an argument for the new password (`new_password` here); rename or wrap as needed to match your actual function signatures.
4. The recovery functions raise `HTTPException` with 404 or 410 for expired sessions. If they return responses instead of raising, update the assertions to check the returned status/shape instead of catching exceptions.
5. If your implementation consumes valid tokens (removing them from `_password_recovery_store` on success), tighten the `assert valid_token in store or valid_token not in store` line to reflect the exact expected behavior (e.g. `assert valid_token not in store`).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread backend/auth_router.py
Comment on lines +265 to +266
def _normalize_password_recovery_scope(scope: str) -> str:
normalized = str(scope or "admin").strip().lower()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 issue (security): Defaulting a falsy scope to 'admin' is risky and may accidentally elevate recovery privileges.

scope or "admin" makes any falsy or empty scope (e.g. missing field, empty string) behave as an admin recovery request, so validation failures can silently become admin flows. Consider either defaulting to a non-privileged scope like "user" or requiring a non-empty scope and raising if it’s falsy.

Comment thread backend/auth_router.py
Comment on lines +626 to +628
if (
session_state.get("scope") == scope
and compare_digest(str(session_state.get("reset_token") or ""), payload.reset_token)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider normalizing the incoming reset token before constant-time comparison to reduce UX friction.

payload.reset_token is compared verbatim to a normalized session token. If the client sends the correct token with extra whitespace (e.g. from copy‑paste), compare_digest will fail. Trimming or otherwise normalizing payload.reset_token (for example, payload.reset_token.strip()) before comparison would handle these cases without affecting security.

Suggested implementation:

    scope = _normalize_password_recovery_scope(payload.scope)
    normalized_reset_token = (payload.reset_token or "").strip()
    matched_session = None
    for session_token, session_state in _password_recovery_store.items():
        if (
            session_state.get("scope") == scope
            and compare_digest(str(session_state.get("reset_token") or ""), normalized_reset_token)
        ):

Comment on lines +58 to +67
def test_admin_tokens_expire_by_default(monkeypatch):
monkeypatch.delenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", raising=False)
auth_router = _load_auth_router(monkeypatch)
admin_user = SimpleNamespace(is_admin=True, is_superuser=False)

assert auth_router._should_issue_non_expiring_admin_token(admin_user) is False

monkeypatch.setenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", "true")
auth_router = _load_auth_router(monkeypatch)
assert auth_router._should_issue_non_expiring_admin_token(admin_user) is True
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Add parametrized tests for all supported ALLOW_NON_EXPIRING_ADMIN_TOKENS values and non-admin users

This test only covers the default and a single truthy value. Since _should_issue_non_expiring_admin_token accepts multiple truthy strings and depends on admin/superuser flags, please parameterize it to cover:

  • All accepted truthy values (e.g. "1", "true", "yes", "on", plus casing/whitespace variants) returning True for an admin user.
  • A non-admin user returning False even when the env var is a truthy value.
  • Falsy/invalid values (e.g. "false", "0", "random") returning False for an admin user.

This will better guard against regressions and ensure the env flag semantics remain consistent.

Suggested implementation:

import pytest
from fastapi import HTTPException
from types import SimpleNamespace
@pytest.mark.parametrize(
    "env_value",
    [
        "1",
        "true",
        "yes",
        "on",
        "TRUE",
        "Yes",
        "On",
        "  true  ",
    ],
)
def test_should_issue_non_expiring_admin_token_for_truthy_values(monkeypatch, env_value):
    monkeypatch.setenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", env_value)
    auth_router = _load_auth_router(monkeypatch)
    admin_user = SimpleNamespace(is_admin=True, is_superuser=False)

    assert auth_router._should_issue_non_expiring_admin_token(admin_user) is True


@pytest.mark.parametrize(
    "env_value",
    [
        None,  # unset / default
        "",
        "false",
        "0",
        "no",
        "off",
        "FALSE",
        "No",
        "Off",
        "random",
        "  ",
    ],
)
def test_should_not_issue_non_expiring_admin_token_for_falsy_or_invalid_values(
    monkeypatch, env_value
):
    if env_value is None:
        monkeypatch.delenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", raising=False)
    else:
        monkeypatch.setenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", env_value)

    auth_router = _load_auth_router(monkeypatch)
    admin_user = SimpleNamespace(is_admin=True, is_superuser=False)

    assert auth_router._should_issue_non_expiring_admin_token(admin_user) is False


@pytest.mark.parametrize(
    "env_value",
    [
        "1",
        "true",
        "yes",
        "on",
        "TRUE",
        "Yes",
        "On",
        "  true  ",
    ],
)
def test_should_not_issue_non_expiring_token_for_non_admin_users(monkeypatch, env_value):
    monkeypatch.setenv("ALLOW_NON_EXPIRING_ADMIN_TOKENS", env_value)
    auth_router = _load_auth_router(monkeypatch)
    non_admin_user = SimpleNamespace(is_admin=False, is_superuser=False)

    assert auth_router._should_issue_non_expiring_admin_token(non_admin_user) is False

Comment on lines +70 to +86
def test_start_password_recovery_uses_random_verification_code(monkeypatch):
auth_router = _load_auth_router(monkeypatch)
auth_router._password_recovery_store.clear()
monkeypatch.setattr(auth_router, "randbelow", lambda upper_bound: 123456)
db = _FakeDB(SimpleNamespace(id=7, is_admin=True, is_superuser=False))

response = auth_router.start_password_recovery(
auth_router.PasswordRecoveryStartRequest(
scope="admin",
user_hint="admin@example.com",
),
db,
)

session_state = auth_router._password_recovery_store[response["recovery_session_token"]]
assert session_state["verification_code"] == "123456"
assert session_state["verification_code"] != "000000"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Cover zero-padding and multi-session behavior of the recovery verification code

To strengthen this test, consider adding:

  • Zero-padding: monkeypatch randbelow to return a small value (e.g. 42) and assert verification_code == "000042" to cover the formatting logic.
  • Multi-session uniqueness: create two sessions in sequence with different randbelow outputs and assert their verification codes differ, confirming per-session randomness.

These can be added via parametrization or as a dedicated padding/uniqueness test.

Suggested change
def test_start_password_recovery_uses_random_verification_code(monkeypatch):
auth_router = _load_auth_router(monkeypatch)
auth_router._password_recovery_store.clear()
monkeypatch.setattr(auth_router, "randbelow", lambda upper_bound: 123456)
db = _FakeDB(SimpleNamespace(id=7, is_admin=True, is_superuser=False))
response = auth_router.start_password_recovery(
auth_router.PasswordRecoveryStartRequest(
scope="admin",
user_hint="admin@example.com",
),
db,
)
session_state = auth_router._password_recovery_store[response["recovery_session_token"]]
assert session_state["verification_code"] == "123456"
assert session_state["verification_code"] != "000000"
def test_start_password_recovery_uses_random_verification_code(monkeypatch):
auth_router = _load_auth_router(monkeypatch)
auth_router._password_recovery_store.clear()
monkeypatch.setattr(auth_router, "randbelow", lambda upper_bound: 123456)
db = _FakeDB(SimpleNamespace(id=7, is_admin=True, is_superuser=False))
response = auth_router.start_password_recovery(
auth_router.PasswordRecoveryStartRequest(
scope="admin",
user_hint="admin@example.com",
),
db,
)
session_state = auth_router._password_recovery_store[response["recovery_session_token"]]
assert session_state["verification_code"] == "123456"
assert session_state["verification_code"] != "000000"
def test_start_password_recovery_zero_pads_verification_code(monkeypatch):
auth_router = _load_auth_router(monkeypatch)
auth_router._password_recovery_store.clear()
# Force a small random value to exercise zero-padding logic
monkeypatch.setattr(auth_router, "randbelow", lambda upper_bound: 42)
db = _FakeDB(SimpleNamespace(id=7, is_admin=True, is_superuser=False))
response = auth_router.start_password_recovery(
auth_router.PasswordRecoveryStartRequest(
scope="admin",
user_hint="admin@example.com",
),
db,
)
session_state = auth_router._password_recovery_store[response["recovery_session_token"]]
assert session_state["verification_code"] == "000042"
def test_start_password_recovery_generates_unique_codes_per_session(monkeypatch):
auth_router = _load_auth_router(monkeypatch)
auth_router._password_recovery_store.clear()
# Simulate different random outputs for consecutive sessions
random_values = iter([123456, 654321])
def _fake_randbelow(upper_bound):
return next(random_values)
monkeypatch.setattr(auth_router, "randbelow", _fake_randbelow)
db = _FakeDB(SimpleNamespace(id=7, is_admin=True, is_superuser=False))
response1 = auth_router.start_password_recovery(
auth_router.PasswordRecoveryStartRequest(
scope="admin",
user_hint="admin1@example.com",
),
db,
)
response2 = auth_router.start_password_recovery(
auth_router.PasswordRecoveryStartRequest(
scope="admin",
user_hint="admin2@example.com",
),
db,
)
session_state1 = auth_router._password_recovery_store[response1["recovery_session_token"]]
session_state2 = auth_router._password_recovery_store[response2["recovery_session_token"]]
assert session_state1["verification_code"] == "123456"
assert session_state2["verification_code"] == "654321"
assert session_state1["verification_code"] != session_state2["verification_code"]

Comment on lines +89 to +98
def test_password_recovery_verify_identity_limits_failed_attempts(monkeypatch):
auth_router = _load_auth_router(monkeypatch)
auth_router._password_recovery_store.clear()
recovery_session_token = "recovery_test"
auth_router._password_recovery_store[recovery_session_token] = {
"user_id": 1,
"scope": "admin",
"verified": False,
"verification_code": "654321",
"verification_attempts": 0,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Add a positive-path test for identity verification, including reset of attempt counter and reset-token issuance

This test covers the failure path and 401/429 behavior well. To fully cover verify_password_recovery_identity, please also add a positive-path test that:

  • Begins with a session where verification_attempts > 0,
  • Submits a correct verification_code,
  • Asserts that:
    • session_state["verified"] becomes True,
    • session_state["verification_attempts"] is reset to 0,
    • identity_session_token, reset_token, and reset_expires_at are correctly set,
    • The response exposes a usable reset_token.

This will guard against regressions in the successful verification flow while enforcing the attempt limit.

Suggested implementation:

def test_password_recovery_verify_identity_limits_failed_attempts(monkeypatch):


def test_password_recovery_verify_identity_success_resets_attempts_and_issues_reset_token(monkeypatch, db):
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()

    recovery_session_token = "recovery_test_success"
    auth_router._password_recovery_store[recovery_session_token] = {
        "user_id": 1,
        "scope": "admin",
        "verified": False,
        "verification_code": "654321",
        "verification_attempts": 2,
        "expires_at": datetime.utcnow() + timedelta(minutes=5),
    }

    response = auth_router.verify_password_recovery_identity(
        recovery_session_token=recovery_session_token,
        verification_code="654321",
        db=db,
    )

    session_state = auth_router._password_recovery_store[recovery_session_token]

    # verification flag should be set
    assert session_state["verified"] is True
    # attempts counter should be reset
    assert session_state["verification_attempts"] == 0

    # reset / identity session fields should be issued
    assert "identity_session_token" in session_state
    assert "reset_token" in session_state
    assert "reset_expires_at" in session_state

    # response should expose usable reset_token
    assert response["reset_token"] == session_state["reset_token"]

To wire this in cleanly you may need to:

  1. Confirm the verification entry point and adapt the call accordingly:
    • If the API is different (e.g. verify_password_recovery_identity(db, recovery_session_token, verification_code) or an HTTP route tested via a test client), adjust the response = ... line to use the actual call pattern and access the returned JSON body appropriately.
  2. Ensure that the db fixture is available in this test module (other tests in the file likely already use it; if not, add or import it).
  3. Place this new test at top-level (same indentation as other tests) and immediately after the existing test_password_recovery_verify_identity_limits_failed_attempts so both success and failure paths live together.
  4. If your implementation uses different session-state keys (e.g. "identity_session_token" vs "password_recovery_session_token"), update the asserted keys to match the actual implementation.

Comment on lines +118 to +127
def test_reset_password_requires_verified_identity(monkeypatch):
auth_router = _load_auth_router(monkeypatch)
auth_router._password_recovery_store.clear()
auth_router._password_recovery_store["recovery_test"] = {
"user_id": 1,
"scope": "admin",
"verified": False,
"reset_token": "reset_token",
"reset_expires_at": datetime.utcnow() + timedelta(minutes=5),
"expires_at": datetime.utcnow() + timedelta(minutes=5),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Distinguish between unverified and missing identity session token in reset-password tests

This test covers the verified=False → 403 behavior. The implementation also requires a non-empty identity_session_token. Please add a case where verified=True but identity_session_token is empty/whitespace or missing, and a reset with a valid reset_token still returns 403. That will exercise the identity proof requirement and help catch regressions where the token is ignored once verified is true.

Suggested implementation:

def test_reset_password_requires_verified_identity(monkeypatch):
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()

    # Case 1: identity not verified → reset must be forbidden even with a valid reset token
    auth_router._password_recovery_store["recovery_test"] = {
        "user_id": 1,
        "scope": "admin",
        "verified": False,
        "reset_token": "reset_token",
        "reset_expires_at": datetime.utcnow() + timedelta(minutes=5),
        "expires_at": datetime.utcnow() + timedelta(minutes=5),
    }

    with pytest.raises(HTTPException) as exc_info:
        # use whatever helper/reset endpoint is used elsewhere in this file
        auth_router.reset_password(
            recovery_session_token="recovery_test",
            reset_token="reset_token",
            new_password="new-password-1",
        )
    assert exc_info.value.status_code == 403

    # Case 2: identity marked verified but missing/blank identity_session_token → still forbidden
    auth_router._password_recovery_store["recovery_test"] = {
        "user_id": 1,
        "scope": "admin",
        "verified": True,
        # intentionally omit or blank out identity_session_token to simulate missing proof
        "identity_session_token": "   ",
        "reset_token": "reset_token",
        "reset_expires_at": datetime.utcnow() + timedelta(minutes=5),
        "expires_at": datetime.utcnow() + timedelta(minutes=5),
    }

    with pytest.raises(HTTPException) as exc_info:
        auth_router.reset_password(
            recovery_session_token="recovery_test",
            reset_token="reset_token",
            new_password="new-password-2",
        )
    assert exc_info.value.status_code == 403
  1. Replace auth_router.reset_password(...) with the actual function/route helper used elsewhere in this test file to perform a password reset, matching its parameter names and call style (e.g. using client.post("/reset-password", json=...) or similar).
  2. Align the payload keys (recovery_session_token, reset_token, new_password) with your actual reset handler signature.
  3. If the real implementation distinguishes between “missing” and “blank” identity_session_token, you may also want to add a third subcase where the key is completely omitted from the store entry.

Comment on lines +143 to +152
def test_reset_password_updates_hash_and_clears_session(monkeypatch):
auth_router = _load_auth_router(monkeypatch)
auth_router._password_recovery_store.clear()
user = SimpleNamespace(id=1, hashed_password="old")
db = _FakeDB(user)
auth_router._password_recovery_store["recovery_test"] = {
"user_id": 1,
"scope": "admin",
"verified": True,
"identity_session_token": "identity-proof",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Add tests for scope normalization and invalid scopes in the recovery flow

The current test only covers the happy path for an admin scope, but the implementation now normalizes and validates scopes in both start_password_recovery and reset_password_via_recovery. Please add tests that:

  • Use mixed-case and whitespace scopes (e.g. " Admin ", "USER") for both start and reset, asserting that recovery succeeds, confirming consistent normalization.
  • Use invalid scopes (e.g. "root", "foobar") for both start and reset, asserting a 400 and the expected error message.

This will ensure the allowed-scope guardrail is properly enforced and cannot be bypassed via casing or whitespace.

Suggested implementation:

def test_reset_password_updates_hash_and_clears_session(monkeypatch):
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    user = SimpleNamespace(id=1, hashed_password="old")
    db = _FakeDB(user)

    # Seed a verified recovery entry for the user
    auth_router._password_recovery_store["recovery_test"] = {
        "user_id": 1,
        "scope": "admin",
        "verified": True,
        "identity_session_token": "identity-proof",
        "reset_token": "reset_token",
    }

    # Perform the reset
    auth_router.reset_password_via_recovery(
        SimpleNamespace(
            scope="admin",
            reset_token="reset_token",
            new_password="new-password-123",
        ),
        db,
    )

    # Password hash must change and recovery entry must be removed
    assert user.hashed_password != "old"
    assert "recovery_test" not in auth_router._password_recovery_store


def test_start_password_recovery_normalizes_scope(monkeypatch):
    """start_password_recovery should accept mixed-case/whitespace scopes."""
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    user = SimpleNamespace(id=1, email="user@example.com", hashed_password="old")
    db = _FakeDB(user)

    # Use mixed-case and whitespace for scope
    request = SimpleNamespace(
        email="user@example.com",
        scope="  Admin  ",
    )

    auth_router.start_password_recovery(request, db)

    # Recovery entry should exist and have normalized scope (e.g. 'admin')
    assert len(auth_router._password_recovery_store) == 1
    recovery = next(iter(auth_router._password_recovery_store.values()))
    assert recovery["user_id"] == user.id
    assert recovery["scope"] == "admin"


def test_start_password_recovery_rejects_invalid_scope(monkeypatch):
    """start_password_recovery should reject invalid scopes."""
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    user = SimpleNamespace(id=1, email="user@example.com", hashed_password="old")
    db = _FakeDB(user)

    for invalid_scope in ["root", "foobar"]:
        request = SimpleNamespace(
            email="user@example.com",
            scope=invalid_scope,
        )

        with pytest.raises(HTTPException) as exc_info:
            auth_router.start_password_recovery(request, db)

        assert exc_info.value.status_code == 400
        # The implementation should expose a clear invalid-scope error message
        assert "invalid scope" in exc_info.value.detail.lower()


def test_reset_password_via_recovery_normalizes_scope(monkeypatch):
    """reset_password_via_recovery should accept mixed-case/whitespace scopes."""
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    user = SimpleNamespace(id=1, hashed_password="old")
    db = _FakeDB(user)

    # Seed a verified recovery entry with normalized scope
    auth_router._password_recovery_store["recovery_test"] = {
        "user_id": 1,
        "scope": "admin",
        "verified": True,
        "identity_session_token": "identity-proof",
        "reset_token": "reset_token",
    }

    # Call reset with mixed-case and extra whitespace in scope
    auth_router.reset_password_via_recovery(
        SimpleNamespace(
            scope="  Admin  ",
            reset_token="reset_token",
            new_password="new-password-123",
        ),
        db,
    )

    # Ensure the reset still succeeds (hash changes and entry cleared)
    assert user.hashed_password != "old"
    assert "recovery_test" not in auth_router._password_recovery_store


def test_reset_password_via_recovery_rejects_invalid_scope(monkeypatch):
    """reset_password_via_recovery should reject invalid scopes."""
    auth_router = _load_auth_router(monkeypatch)
    auth_router._password_recovery_store.clear()
    user = SimpleNamespace(id=1, hashed_password="old")
    db = _FakeDB(user)

    # Seed a verified recovery entry with an allowed scope
    auth_router._password_recovery_store["recovery_test"] = {
        "user_id": 1,
        "scope": "admin",
        "verified": True,
        "identity_session_token": "identity-proof",
        "reset_token": "reset_token",
    }

    for invalid_scope in ["root", "foobar"]:
        with pytest.raises(HTTPException) as exc_info:
            auth_router.reset_password_via_recovery(
                SimpleNamespace(
                    scope=invalid_scope,
                    reset_token="reset_token",
                    new_password="new-password-123",
                ),
                db,
            )

        assert exc_info.value.status_code == 400
        assert "invalid scope" in exc_info.value.detail.lower()

The above tests assume the following, based on typical patterns in this file:

  1. start_password_recovery(request, db) accepts a request object with email and scope attributes and raises HTTPException on invalid scope, with a message that includes "invalid scope".
  2. reset_password_via_recovery(request, db) will:
    • Normalize the scope from the request (trimming whitespace and normalizing case) and compare it against allowed scopes.
    • Raise HTTPException(status_code=400, detail="...invalid scope...") when the scope is invalid.
  3. auth_router._password_recovery_store is a dict keyed by token with values containing at least user_id, scope, verified, identity_session_token, and reset_token.

If your actual request/DB interfaces or error messages differ, adjust:

  • The SimpleNamespace fields used to construct the request objects.
  • The error-message substring checks ("invalid scope").
  • Any additional assertions you want (e.g., checking that the identity session is cleared) to match your implementation.

Comment on lines +38 to +47
def _load_auth_router(monkeypatch):
sys.modules.pop("backend.auth_router", None)

fake_database = types.ModuleType("backend.database")
fake_database.get_db = lambda: None

fake_models = types.ModuleType("backend.models")

class _StubUser:
id = "id"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Add coverage for purging expired password recovery sessions before start/verify/reset

Since _purge_expired_password_recovery_sessions is now invoked by all three recovery endpoints, it’d be helpful to add tests that:

  • Populate _password_recovery_store with both an expired and a valid session.
  • Invoke start_password_recovery, verify_password_recovery_identity, or reset_password_via_recovery.
  • Assert that the expired session is removed and the endpoint response reflects the expiry (e.g. 404/410), while valid sessions still succeed.

This will keep the purge behavior verified as part of the recovery flow.

Suggested implementation:

import datetime

import pytest
from fastapi import HTTPException
class _FakeQuery:
    def __init__(self, user):
        self._user = user

    def filter(self, *args, **kwargs):
        return self


def _make_recovery_session(user_id: str, expires_at: datetime.datetime) -> dict:
    return {
        "user_id": user_id,
        "expires_at": expires_at,
    }


def test_start_password_recovery_purges_expired_sessions(monkeypatch):
    """
    When start_password_recovery is called, expired sessions should be purged
    while valid sessions remain usable.
    """
    auth_router = _load_auth_router(monkeypatch)

    store = auth_router._password_recovery_store
    store.clear()

    now = datetime.datetime.utcnow()
    expired_token = "expired-token"
    valid_token = "valid-token"

    store[expired_token] = _make_recovery_session("id", now - datetime.timedelta(minutes=5))
    store[valid_token] = _make_recovery_session("id", now + datetime.timedelta(minutes=5))

    # Calling the endpoint should purge expired sessions.
    # We expect the call path for an expired recovery flow to ultimately raise HTTPException.
    with pytest.raises(HTTPException) as excinfo:
        # The exact call signature may vary (e.g. a Pydantic model instead of a bare email),
        # but the point is to exercise the start_password_recovery flow.
        auth_router.start_password_recovery(email="email")

    assert excinfo.value.status_code in (404, 410)
    assert expired_token not in store
    assert valid_token in store


def test_verify_password_recovery_identity_purges_expired_sessions(monkeypatch):
    """
    When verify_password_recovery_identity is called, it should purge expired
    sessions and fail for expired tokens while still succeeding for valid tokens.
    """
    auth_router = _load_auth_router(monkeypatch)

    store = auth_router._password_recovery_store
    store.clear()

    now = datetime.datetime.utcnow()
    expired_token = "expired-token"
    valid_token = "valid-token"

    store[expired_token] = _make_recovery_session("id", now - datetime.timedelta(minutes=5))
    store[valid_token] = _make_recovery_session("id", now + datetime.timedelta(minutes=5))

    # Expired token should cause an HTTPException and be removed from the store.
    with pytest.raises(HTTPException) as excinfo:
        auth_router.verify_password_recovery_identity(token=expired_token)

    assert excinfo.value.status_code in (404, 410)
    assert expired_token not in store

    # Valid token should still succeed and remain in the store (or transition to the next state)
    auth_router.verify_password_recovery_identity(token=valid_token)
    assert valid_token in store or valid_token not in store  # allow for flows that consume the token


def test_reset_password_via_recovery_purges_expired_sessions(monkeypatch):
    """
    When reset_password_via_recovery is called, it should purge expired
    sessions and reject resets for expired tokens, while still allowing
    resets with valid tokens.
    """
    auth_router = _load_auth_router(monkeypatch)

    store = auth_router._password_recovery_store
    store.clear()

    now = datetime.datetime.utcnow()
    expired_token = "expired-token"
    valid_token = "valid-token"

    store[expired_token] = _make_recovery_session("id", now - datetime.timedelta(minutes=5))
    store[valid_token] = _make_recovery_session("id", now + datetime.timedelta(minutes=5))

    # Expired token reset attempt should fail and purge the expired session.
    with pytest.raises(HTTPException) as excinfo:
        auth_router.reset_password_via_recovery(
            token=expired_token,
            new_password="new-password",
        )

    assert excinfo.value.status_code in (404, 410)
    assert expired_token not in store

    # Valid token reset attempt should succeed.
    auth_router.reset_password_via_recovery(
        token=valid_token,
        new_password="new-password",
    )
    # Depending on implementation, the token may be consumed; the important
    # behavior here is that no exception is raised and the expired token is gone.

The above tests assume:

  1. backend.auth_router exposes:
    • _password_recovery_store as a mutable mapping from token to a dict containing at least user_id and expires_at: datetime.
    • Functions start_password_recovery, verify_password_recovery_identity, and reset_password_via_recovery callable as shown.
  2. start_password_recovery accepts an email keyword argument; if it instead expects a Pydantic model or different parameters, adjust the call to match.
  3. verify_password_recovery_identity and reset_password_via_recovery accept a token parameter, and reset_password_via_recovery accepts an argument for the new password (new_password here); rename or wrap as needed to match your actual function signatures.
  4. The recovery functions raise HTTPException with 404 or 410 for expired sessions. If they return responses instead of raising, update the assertions to check the returned status/shape instead of catching exceptions.
  5. If your implementation consumes valid tokens (removing them from _password_recovery_store on success), tighten the assert valid_token in store or valid_token not in store line to reflect the exact expected behavior (e.g. assert valid_token not in store).

Copy link
Copy Markdown
Owner

@parkcheolhong parkcheolhong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고했어요

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens security-sensitive auth flows by tightening password recovery session handling (randomized verification codes, attempt limiting, scope normalization, stale session purging) and by making non-expiring admin tokens opt-in via environment configuration.

Changes:

  • Make issuance of non-expiring admin tokens opt-in via ALLOW_NON_EXPIRING_ADMIN_TOKENS.
  • Harden password recovery by generating random 6-digit verification codes, validating/normalizing scopes, purging expired sessions, and using constant-time comparisons.
  • Add regression tests covering admin token defaults and the tightened recovery flow (random code, retry limit, verified-identity requirement, and successful reset behavior).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
backend/auth_router.py Implements stricter admin token policy and hardens password recovery session lifecycle, scope validation, and verification/reset checks.
tests/test_auth_router_security.py Adds focused tests for the new admin token default behavior and recovery hardening paths.

Comment thread backend/auth_router.py
Comment on lines +43 to +45
_PASSWORD_RECOVERY_MAX_VERIFY_ATTEMPTS = max(
1,
int(os.getenv("PASSWORD_RECOVERY_MAX_VERIFY_ATTEMPTS", "5")),
Comment thread backend/auth_router.py
Comment on lines +275 to +282
def _purge_expired_password_recovery_sessions() -> None:
now = datetime.utcnow()
expired_tokens = [
session_token
for session_token, session_state in _password_recovery_store.items()
if not isinstance(session_state.get("expires_at"), datetime)
or cast(datetime, session_state["expires_at"]) <= now
]
Comment thread backend/auth_router.py


def _issue_recovery_verification_code() -> str:
return f"{randbelow(1_000_000):06d}"
parkcheolhong added a commit that referenced this pull request May 11, 2026
* Potential fix for code scanning alert no. 2: Binding a socket to all network interfaces (#5)

* Potential fix for code scanning alert no. 2: Binding a socket to all network interfaces

수정해줘

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Fix profiler backend default host to loopback

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix: harden auth recovery security (#6)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/3d52b2c5-9c5a-43f7-91a5-9587bc9ce9a5

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Copilot/fix unauthorized data in path expression (#15)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* 검증확인했습니다, 병합해주세요 (#14)

* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Update .github/workflows/codeql.yml

변경 감사합니다

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

* Potential fix for pull request finding

커밋합니다.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: address PR review feedback for auth and progress persistence

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/54ddac5c-9ffc-4dd9-8328-a90404f7b582

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

수정해주세요

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

수정해주세요

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

변경해주세요,

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항에 맞게 수정해주세요.

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항 감사합니다, 수정해주세요

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

수정해주세요

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Harden orchestrator progress file paths and profiler bind host policy (#17)

* fix: harden path handling and profiler bind defaults for CodeQL alerts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: address review nits for host and run_id normalization

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: tighten localhost and hostname validation for profiler bind

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: improve profiler host validation diagnostics

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
parkcheolhong added a commit that referenced this pull request May 11, 2026
* Potential fix for code scanning alert no. 2: Binding a socket to all network interfaces (#5)

* Potential fix for code scanning alert no. 2: Binding a socket to all network interfaces

수정해줘



* Fix profiler backend default host to loopback

---------



* fix: harden auth recovery security (#6)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/3d52b2c5-9c5a-43f7-91a5-9587bc9ce9a5




* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



---------




* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



---------




* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



---------




* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)



* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac




* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



---------




* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



---------




* Copilot/fix unauthorized data in path expression (#15)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* 검증확인했습니다, 병합해주세요 (#14)

* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



---------




* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



---------




* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



---------




* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)



* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac




* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



---------




* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



---------




---------




* Update .github/workflows/codeql.yml

변경 감사합니다



* Potential fix for pull request finding

커밋합니다.



* fix: address PR review feedback for auth and progress persistence

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/54ddac5c-9ffc-4dd9-8328-a90404f7b582



---------






* Potential fix for pull request finding

수정해주세요



* Potential fix for pull request finding

수정해주세요



* Potential fix for pull request finding

변경해주세요,



* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항에 맞게 수정해주세요.



* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항 감사합니다, 수정해주세요



* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

수정해주세요



* Harden orchestrator progress file paths and profiler bind host policy (#17)

* fix: harden path handling and profiler bind defaults for CodeQL alerts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



* chore: address review nits for host and run_id normalization

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



* fix: tighten localhost and hostname validation for profiler bind

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



* chore: improve profiler host validation diagnostics

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



---------




---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
parkcheolhong added a commit that referenced this pull request May 11, 2026
* fix: harden auth recovery security

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/3d52b2c5-9c5a-43f7-91a5-9587bc9ce9a5

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Copilot/fix unauthorized data in path expression (#15)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* 검증확인했습니다, 병합해주세요 (#14)

* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Update .github/workflows/codeql.yml

변경 감사합니다

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

* Potential fix for pull request finding

커밋합니다.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: address PR review feedback for auth and progress persistence

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/54ddac5c-9ffc-4dd9-8328-a90404f7b582

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

수정해주세요

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

수정해주세요

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

변경해주세요,

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항에 맞게 수정해주세요.

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항 감사합니다, 수정해주세요

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

수정해주세요

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Harden orchestrator progress file paths and profiler bind host policy (#17)

* fix: harden path handling and profiler bind defaults for CodeQL alerts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: address review nits for host and run_id normalization

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: tighten localhost and hostname validation for profiler bind

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: improve profiler host validation diagnostics

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* 병합해주세요 (#16) (#18)

* Potential fix for code scanning alert no. 2: Binding a socket to all network interfaces (#5)

* Potential fix for code scanning alert no. 2: Binding a socket to all network interfaces

수정해줘



* Fix profiler backend default host to loopback

---------



* fix: harden auth recovery security (#6)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/3d52b2c5-9c5a-43f7-91a5-9587bc9ce9a5




* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



---------




* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



---------




* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



---------




* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)



* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac




* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



---------




* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



---------




* Copilot/fix unauthorized data in path expression (#15)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* 검증확인했습니다, 병합해주세요 (#14)

* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



---------




* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



---------




* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



---------




* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)



* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac




* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



---------




* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



---------




---------




* Update .github/workflows/codeql.yml

변경 감사합니다



* Potential fix for pull request finding

커밋합니다.



* fix: address PR review feedback for auth and progress persistence

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/54ddac5c-9ffc-4dd9-8328-a90404f7b582



---------






* Potential fix for pull request finding

수정해주세요



* Potential fix for pull request finding

수정해주세요



* Potential fix for pull request finding

변경해주세요,



* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항에 맞게 수정해주세요.



* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항 감사합니다, 수정해주세요



* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

수정해주세요



* Harden orchestrator progress file paths and profiler bind host policy (#17)

* fix: harden path handling and profiler bind defaults for CodeQL alerts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



* chore: address review nits for host and run_id normalization

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



* fix: tighten localhost and hostname validation for profiler bind

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



* chore: improve profiler host validation diagnostics

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



---------




---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
parkcheolhong added a commit that referenced this pull request May 11, 2026
* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* 병합 확인  (#19)

* fix: harden auth recovery security

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/3d52b2c5-9c5a-43f7-91a5-9587bc9ce9a5

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Copilot/fix unauthorized data in path expression (#15)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* 검증확인했습니다, 병합해주세요 (#14)

* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Update .github/workflows/codeql.yml

변경 감사합니다

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

* Potential fix for pull request finding

커밋합니다.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: address PR review feedback for auth and progress persistence

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/54ddac5c-9ffc-4dd9-8328-a90404f7b582

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

수정해주세요

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

수정해주세요

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

변경해주세요,

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항에 맞게 수정해주세요.

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항 감사합니다, 수정해주세요

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

수정해주세요

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Harden orchestrator progress file paths and profiler bind host policy (#17)

* fix: harden path handling and profiler bind defaults for CodeQL alerts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: address review nits for host and run_id normalization

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* fix: tighten localhost and hostname validation for profiler bind

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* chore: improve profiler host validation diagnostics

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2

Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: parkcheolhong <111139476+parkcheolhong@users.noreply.github.com>

* 병합해주세요 (#16) (#18)

* Potential fix for code scanning alert no. 2: Binding a socket to all network interfaces (#5)

* Potential fix for code scanning alert no. 2: Binding a socket to all network interfaces

수정해줘



* Fix profiler backend default host to loopback

---------



* fix: harden auth recovery security (#6)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/3d52b2c5-9c5a-43f7-91a5-9587bc9ce9a5




* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



---------




* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



---------




* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



---------




* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)



* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac




* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



---------




* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



---------




* Copilot/fix unauthorized data in path expression (#15)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* 검증확인했습니다, 병합해주세요 (#14)

* Harden Pillow dependency floor to patched range for active image parsing CVEs (#7)

* chore: raise Pillow minimum version to 12.2

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



* chore: remove accidental pycache artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/9ec743ae-a698-4cc0-aa87-8825771cb8d6



---------




* Harden orchestrator/auth error surfaces and remove CodeQL-flagged unsafe patterns (#8)

* chore: start codeql alert remediation plan

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: remediate CodeQL security and quality findings

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



* fix: finalize CodeQL remediation hardening updates

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/e096e163-c0eb-430e-95b8-006690b13d72



---------




* Sanitize health diagnostic errors to avoid exception detail exposure (#9)

* fix: redact health diagnostic exception details

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: make health sanitization checks portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* chore: remove compiled test artifacts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: normalize diagnostic error codes

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* test: share diagnostic error code fixture

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



* refactor: simplify safe diagnostic code map

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/5d18c2d0-8dda-4817-837b-37752598afa6



---------




* Potential fix for code scanning alert no. 4: Information exposure through an exception (#10)



* fix(ci): set explicit python-version in codeql workflow (#11)

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/4ea2a28e-7f09-4b9d-a3df-785939fa43ac




* fix: webauthn stub in tests, timezone-aware datetimes, Pydantic v2 ConfigDict, add .gitignore (#12)

* fix(tests): stub webauthn in auth_router test fixture to fix import failures

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



* fix: stub webauthn in tests, replace datetime.utcnow, fix Pydantic Config, add .gitignore

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/63299979-62f4-489f-a1d2-307336759de9



---------




* Add consolidated design-change report and expanded PR body draft (#13)

* docs: add overall design change and PR report

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: make PR report paths portable

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



* docs: clarify bilingual PR report structure

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/82b0addf-4e64-42b9-ac75-63d99a14f84d



---------




---------




* Update .github/workflows/codeql.yml

변경 감사합니다



* Potential fix for pull request finding

커밋합니다.



* fix: address PR review feedback for auth and progress persistence

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/54ddac5c-9ffc-4dd9-8328-a90404f7b582



---------






* Potential fix for pull request finding

수정해주세요



* Potential fix for pull request finding

수정해주세요



* Potential fix for pull request finding

변경해주세요,



* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항에 맞게 수정해주세요.



* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

제안 사항 감사합니다, 수정해주세요



* Potential fix for pull request finding 'CodeQL / Uncontrolled data used in path expression'

수정해주세요



* Harden orchestrator progress file paths and profiler bind host policy (#17)

* fix: harden path handling and profiler bind defaults for CodeQL alerts

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



* chore: address review nits for host and run_id normalization

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



* fix: tighten localhost and hostname validation for profiler bind

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



* chore: improve profiler host validation diagnostics

Agent-Logs-Url: https://github.com/parkcheolhong/codeAI/sessions/320282cc-04c8-415c-bacc-8f409266cde2



---------




---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants