Skip to content

fix(scanner): distinguish password indirection and authenticated boundary comments from real findings #1106

Description

@seonghobae

Downstream failure

LifeOS PR #198 exact head 8a9e417b15f89f972e242e07197a3a4a818ff82a ran AppGuardrail workflow 33925458503 on 2026-09-05. Checkout, scanner execution, detector-contract verification, SARIF upload, and retained-evidence upload all succeeded; only the blocking-enforcement step failed. The retained appguardrail-evidence artifact is 9960678559, SHA-256 3e6fe87e28ce13c41e6f1430d5b1a03071a5f7e810935c3607f15d70e67ef6fd.

Fresh retained evidence reproduces scanner-owned false positives on unchanged downstream source. These should be repaired here rather than suppressed or cosmetically rewritten in LifeOS:

  1. hardcoded-password treats variable indirection as a literal secret. infra/postgres/provision/notification-runtime.psql uses PASSWORD :'runtime_password'; infra/postgres/provision/upgrade-legacy-local.sh forwards operator-provided POSTGRES_PASSWORD, LEGACY_POSTGRES_PASSWORD, NOTIFICATION_RUNTIME_DATABASE_PASSWORD, and PGPASSWORD through environment/psql variables. No secret literal is embedded by those expressions.
  2. hardcoded-password also marks assertions in packages/commercial-development-agent/src/compose-runtime-workflow-regression.test.mjs as deploy-blocking application code even though the file is an explicit *.test.mjs regression contract.
  3. hardcoded-database-url marks credential-free postgresql://runtime.invalid/... sentinels in apps/notification-service/src/notification-http.test.ts as deploy-blocking application evidence. .invalid is deliberately non-routable test authority and the URI contains no credentials.
  4. todo-skip-auth fires on the explanatory production comment Requires one ordinary JSON object so prototypes cannot add hidden authority fields. in notification-data-rights-http-boundary.ts. The comment documents prototype/authority validation and expresses no skip, disable, bypass, or deferral of authentication.
  5. Test-context classification is path-shape sensitive: explicit *.test.ts / *.test.mjs files under src/ or another production-looking directory can remain app-code, so otherwise test-only findings become deploy-blocking. Context should be derived from test-file semantics as well as directory names.

Two positive-control fixture findings remain expected and must continue to be detected: tests/appguardrail-fixtures/oauth-open-redirect.ts and tests/appguardrail-fixtures/dangerous-cors.ts. Do not broadly exempt tests from detection; distinguish realistic test evidence from deploy-blocking production evidence while preserving test findings as non-deploy-blocking where appropriate.

Required RED → GREEN

Add scanner-owned regressions before changing classification:

  • RED: shell self/variable assignment (POSTGRES_PASSWORD="$POSTGRES_PASSWORD", PGPASSWORD="$LEGACY_POSTGRES_PASSWORD") and psql variable use (PASSWORD :'runtime_password') are not hardcoded-password; a real literal such as password='secret123' remains detected.
  • RED: *.test.ts and *.test.mjs are classified as test context even when located under src/; scanner findings may still exist but must not become deploy-blocking solely because of directory placement.
  • RED: a credential-free postgresql://runtime.invalid/... value in explicit test context is not deploy-blocking; a credential-bearing production literal remains blocking.
  • RED: ordinary comments containing words such as prototypes, hidden authority fields, or authentication do not become todo-skip-auth unless the comment actually expresses skip/disable/bypass/defer intent; existing true-positive skip-auth fixtures remain detected.
  • GREEN: rerun the scanner fixture suite plus the retained LifeOS cases and prove the expected positive controls still fire, false positives above do not block, and evidence schema/rule IDs remain stable unless a versioned contract change is explicitly required.

Prefer semantic/context discrimination over broad allowlists. Produce an immutable reviewed AppGuardrail release/commit after GREEN so LifeOS can update the exact pin and rerun #198 without source contortions or gate weakening.

Refs ContextualWisdomLab/life-os#198, ContextualWisdomLab/life-os#212.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority: mediumNormal-priority or P2 work

    Type

    No type

    Projects

    • Status
      Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions