Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| de3d5031c8 | |||
| 88bcd6d91c | |||
| 0a17a33db7 | |||
| 1bbd1612a9 |
+41
@@ -0,0 +1,41 @@
|
||||
# Jobjakt Security Policy
|
||||
|
||||
## System and scope
|
||||
|
||||
Jobjakt manages private career profiles, CVs, letters, applications, correspondence and related account data. Review the repository-owned React/Next static-export UI, ASP.NET Core API, EF data and background processing, Python AI/document sidecar, browser extension, deployment/CI configuration and their trust boundaries. Architecture documentation describes nginx, MariaDB, private files and internal services; actual deployed exposure and identity must be verified separately. Retained SQLite and legacy document paths remain in scope while supported.
|
||||
|
||||
This policy supplies review context, not permission to run commands or test live targets. It does not certify existing controls. Root and component policies compose; nearest-path guidance takes precedence.
|
||||
|
||||
## Threat model and trust boundaries
|
||||
|
||||
Consider anonymous callers, two distinct authenticated owners, administrators, revoked or limited sessions, malicious document authors, incoming webhook senders and compromised external services. Treat route/body identifiers, uploaded files, HTML, job advertisements, external callbacks, logs and model output as untrusted.
|
||||
|
||||
Assets include canonical Career Profile facts/history, CV overrides and frozen revisions, application records, attachments, authentication/recovery material, provider tokens, billing entitlements, audit records and recoverable backups. Trace browser-to-API, API-to-database/files/workers, API-to-sidecar and provider callback/outbound fetch boundaries. Do not assume a role, a client UI flag or an internal-network label proves authorization.
|
||||
|
||||
## Security invariants
|
||||
|
||||
- Establish authenticated identity and owner scope before disclosing or changing private data. Caller-supplied owner IDs cannot replace server identity. Apply ownership to nested resources, lists/search, downloads, exports and background work, not only direct item reads.
|
||||
- Enforce administrator and sensitive-operation permissions server-side, including self/last-admin restrictions. Session revocation, recovery, MFA and OAuth state/account-linking controls must preserve the intended identity boundary.
|
||||
- Preserve canonical Career Profile ownership, null-as-inherit CV settings and immutable submitted/frozen snapshots. All applicable application/CV/letter writes must enforce existing revision preconditions and atomic persistence; stale operations must not partially commit or overwrite newer data.
|
||||
- Bound untrusted document/upload/parser work. Validate type, size, owned paths and lifecycle state; reject traversal and unauthorized retrieval. Rendering/import must not execute active content, dereference unapproved URLs, expose local files or change another owner's data.
|
||||
- Treat AI output as a proposal. Keep consent, entitlement, manual fallback, source/revision checks and explicit review/apply boundaries. Private content must not reach an unapproved model/provider; model or document text cannot authorize tool execution.
|
||||
- Validate outbound destinations and redirects at network boundaries. Preserve job-provider rights/attribution and mailbox consent separately from sign-in identity. Validate webhook authenticity, identity binding and replay/idempotency where applicable.
|
||||
- Preserve browser output encoding, safe HTML/rendering boundaries, origin/cookie/CSRF protections and validated return/navigation targets. UI visibility never substitutes for API authorization.
|
||||
- Protect secrets, tokens and private document content in logs, diagnostics, browser bundles, exports and backups. Privacy deletion/retention must account for files, queued work and recovery copies; successful recovery claims require tested database/file/key consistency.
|
||||
- Treat CI/deployment inputs and dependencies as supply-chain boundaries. Review least privilege, secret handling, provenance, image/runtime exposure and reversible recovery; test fixtures or historical reports do not prove production configuration.
|
||||
|
||||
## Reportable findings and severity context
|
||||
|
||||
Report reachable violations with attacker preconditions, affected assets and evidence. Cross-owner private-data disclosure/mutation, account takeover, privilege escalation, unsafe parser/rendering execution, exposed credentials and unauthorized external data transfer warrant impact-based investigation. Separate confirmed reproduction, reasoned likelihood and unverified assumptions.
|
||||
|
||||
Evaluate actual source/configuration and supported deployment modes. A package advisory, missing attribute or hypothetical path alone is not a reproduced exploit; equally, a passing mock test or limited deployment mitigation does not close a reachable issue. Record advisory/reachability and runtime evidence separately. Preserve failed, blocked, skipped and unexecuted checks explicitly.
|
||||
|
||||
## Exclusions and accepted risk
|
||||
|
||||
No vulnerability class, repository component or existing defect is implicitly suppressed. No new risk acceptance, severity downgrade or finding exclusion is granted by this policy. Historical deferred work and compatibility support remain reviewable.
|
||||
|
||||
Production, adjacent networks, real personal data and third-party systems are excluded from active testing unless separately and explicitly authorized. This execution restriction does not exclude review of repository-owned integration or deployment code. Synthetic local fixtures are distinct from approved staging and live-service qualification.
|
||||
|
||||
## Known limitations and qualification
|
||||
|
||||
The independent audit is incomplete. Source analysis, package checks, local fixtures, hosted CI, native accessibility, provider/model behavior, isolated staging and production recovery are separate evidence lanes. Final integrated security review follows relevant application changes. Baseline/deep/final scan results, cost allowance, staging scope and human release acceptance must be recorded separately; none is established by creating this file.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Codex Security scan register
|
||||
|
||||
3 November2026 update: owner approved exact root policy creation/publication. Define-security-policy workflow COMPLETED for root policy only; source base88bcd6d9, exact candidate and resolver results in ../security/ROOT_POLICY_APPROVAL.md. Managed standalone artifact ID/path is documented there; there is no scan ID. Root now resolves for API/UI, nested CV-doc policy remains closest. Baseline/deep/final scans below remain NOT RUN/BLOCKED; no charges, active targets or release acceptance approved. Earlier policy-pending entries are historical.
|
||||
|
||||
2 November 2026. Source baseline `ba826de1e5c959352e4442ab2fec5d02445dd32d`, branch codex/security-offline-preflight. Owner confirms installation; actual tool metadata/skill files verified. Production/third parties excluded. Paid/deep compute allowance pending. ROE: ../security/00-rules-of-engagement.md.
|
||||
|
||||
| Phase/workflow | Status | Actual evidence and limits |
|
||||
| --- | --- | --- |
|
||||
| 00 define-security-policy review | NOT RUN (full workflow); resolver substep COMPLETED | Installed helper resolve-security-md --list exited 0, returned two docs-only policies. No root policy created; proposal/review/approval remains. No scan ID. |
|
||||
| 01 baseline standard scan | NOT RUN | Skill/tool exposure checked; threat-model/policy and capability preflight pending. No scan artifacts or findings. |
|
||||
| 03 deep scan | BLOCKED | Baseline and separately approved compute/cost scope missing. No scan launched. |
|
||||
| 15 final standard and diff scans | NOT RUN | Await baseline, remediation range and independent verification. |
|
||||
|
||||
No scan findings, closure verdicts or human release acceptance are implied by tool availability or regression tests.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Security Phase 00 — offline engagement draft
|
||||
|
||||
2 November 2026. Owner: Connor, direct-chat roadmap authorisation. Source baseline `ba826de1e5c959352e4442ab2fec5d02445dd32d`; isolated branch `codex/security-offline-preflight`. Phase 00 is PARTIAL, not accepted.
|
||||
|
||||
Authorised now: source inspection, harmless synthetic local fixtures, minimal ordinary remediation within approved roadmap boundaries, sanitized reports and branch publication. No network attack target has been approved. Production, adjacent LAN services, real accounts/data, identity/payment/email providers, live AI/models, orchestrator state/keys/configuration/queue and the pre-P10 acceptance worktree are excluded.
|
||||
|
||||
Active staging testing is BLOCKED until exact host/IP, test users/roles, rate/concurrency/duration limits, independent database/storage, disabled egress and recovery/stop controls are approved and verified. Do not infer those from example localhost URLs or repository credentials. Emergency stop: terminate only the named audit-owned fixture process; never stop existing production/user services.
|
||||
|
||||
Proposed fixture boundary: disposable synthetic tenant A, tenant B and administrator; separate temporary data root and database; inert CV files and canary records; mocked OAuth, billing, email, job providers and AI. No routable credentials. Snapshot and restore qualification must precede staged mutation. This plan has not been instantiated or approved for active network testing.
|
||||
|
||||
Evidence: only sanitized reports/test artifacts in Git. Do not inspect real .env values, auth/signing stores or personal documents. Findings require calibrated confidence and safe reproduction; absence of a scan result proves nothing. No root SECURITY.md policy edits, suppressed findings or accepted risks are authorised by this draft.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Phase 01 — partial source-backed threat model
|
||||
|
||||
2 November 2026, baseline ba826de1e5c959352e4442ab2fec5d02445dd32d. PARTIAL; baseline scan NOT RUN. Read the complete Phase 01 prompt and architecture frontend/backend/data-flow/integrations, API reference, security notes and deployment overview. The graph query failed because the new isolated worktree has no graph; direct scoped source review followed. No active network request or live-service test.
|
||||
|
||||
Verified dependency and documented data-flow inventory is in ASSESSMENT_INDEX.md. Threat actors to test: anonymous caller, tenant A, tenant B, administrator, revoked/limited session, malicious document author, incoming webhook sender and compromised external service. Assets: canonical career profile and history, CV/letter snapshots, application records, attachments, OAuth/mail tokens, sessions, billing entitlements, backups and administrative privileges. Secret values have not been inspected.
|
||||
|
||||
Source boundary observations (not proof of a secure deployment):
|
||||
|
||||
- AttachmentsController requires the local authentication scheme. List first queries the requested job; download/rename call FindOwnedAttachmentAsync. Downloads reject unmanaged paths and pending/missing files. Global filter/helper implementation, alternate upload paths and negative tests still need independent audit.
|
||||
- UsersController declares Admin role authorization. Role mutation and reset/email operations require endpoint-specific review; class attributes alone do not establish safe privilege transitions.
|
||||
- BillingController status/checkout/portal explicitly use local authentication; webhook explicitly allows anonymous requests and caps request size at 1 MB. Webhook verifies the Stripe signature via ConstructEvent, rejects invalid signatures, then refreshes subscription state. This can trigger external Stripe egress when configured; do not execute it against a real provider during offline tests. Review identity binding, replay, price qualification and mock negative coverage before acceptance.
|
||||
|
||||
Initial attack tree: reach another tenant's data via object IDs, background execution or shared files; obtain higher privilege via role/session/OAuth flows; cross file/network/model boundaries through uploaded content; forge billing authority through webhook or stale subscription state; expose secrets through public bundles/logs/backups. Each branch requires source tracing plus synthetic negative proof. These are hypotheses, not confirmed vulnerabilities.
|
||||
|
||||
ASVS Level 2 is a proposed planning target for private employment data, not a compliance claim. No unverified requirement IDs or vulnerability identifiers are assigned. Partial endpoint matrix is ENDPOINT_AUTH_MATRIX.csv; tests listed there are candidate existing suites, NOT executed audit evidence. Full route enumeration, middleware/global filter review, deployed exposure and complete endpoint/test mapping remain open.
|
||||
|
||||
Next permitted review: resolve owner filters and attachment sibling paths, inspect auth/session middleware, and complete the source matrix. Baseline standard scan requires the documented capability preflight and recorded results; no scan pass is inferred from this threat model. Root policy changes, if proposed, require exact-diff approval under the policy skill; keep review-only work progressing meanwhile.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Independent security assessment continuation
|
||||
|
||||
3 November2026 — root policy proposal explicitly approved and applied; ROOT_POLICY_APPROVAL.md records exact text identity and successful API/UI/nested policy resolution. This closes the root-policy decision only. Baseline/deep/final scans, current integration target/capability/cost preflight, full matrix and staging/human/release qualifications remain open. No new application/security fix or vulnerability closure is claimed.
|
||||
|
||||
Continuation: ATTACHMENT_OWNERSHIP_REVIEW.md traces the parent ownership filter and corrects the reflection-only test assumption. Fourteen existing relational fixture tests freshly passed on identical Phase 10 backend/test sources; native evidence published at db818e5e. Matrix distinguishes direct controller denials from unexecuted HTTP/list/upload/missing-owner/MariaDB checks. No full security scan or final integrated acceptance is implied.
|
||||
|
||||
Phase 00 offline preflight, 2 November 2026. Branch `codex/security-offline-preflight`, application baseline `ba826de1e5c959352e4442ab2fec5d02445dd32d`. No application/security implementation changed. No staging attacks or production access.
|
||||
|
||||
Read the external master, complete Phase 00 prompt, ROE/finding/release/scan-register templates, repository auditor skill, Codex Security policy and standard-scan skill instructions. Remaining stage prompts must be read before entering their stages. The old master heading “DO NOT START THIS NOW” is superseded for permitted offline work by the owner's later direct execution instruction; protected gates remain.
|
||||
|
||||
Verified inventory: package.json identifies Next 16.4.1, React 19/MUI/TypeScript; API csproj targets .NET 9 with EF SQLite and Pomelo MariaDB, Identity/JWT, Stripe, MailKit; Python requirements identify FastAPI/transformers/document dependencies. These are source dependencies, not deployed identities or proven reachable features. Architecture overview documents nginx/static export -> API -> DB/files/internal AI and provider boundaries; runtime exposure remains unverified. Preserve canonical Career Profile, CV null-as-inherit overrides, letter history and JobApplication.Version/RD21 contracts. No technology-version vulnerability claim is made without advisory/reachability analysis.
|
||||
|
||||
Baseline evidence reused from this exact source ancestry: P10-04 has 89 backend and 92 frontend tests passing, independently source-bound native artifacts. CLEAN-20 has five focused browser checks plus type/lint/build evidence. These are regression evidence, not a completed security audit; this new worktree did not rerun them. Backup parser repair exists on a separate published branch and is not integrated here.
|
||||
|
||||
Plugin exposure: standard/deep scan, draft/artifact/progress tools and documented skill files are available. The actual policy resolver ran successfully and found only docs/cv-import/SECURITY.md and docs/redesign/phase-9/p9-requal-01/SECURITY.md. Neither is an inherited root policy for API/UI source. No baseline/deep scan has run. Root policy creation needs exact proposed diff and separate owner approval under define-security-policy; defer that decision while independent source review continues. No new charge approved; deep scan remains blocked.
|
||||
|
||||
Execution order: finish inventory/threat boundaries and baseline policy review; standard scan after required preflight/gates; deep scan only with cost scope; phases 02–12 offline review/fixture work in source order; active phase 13 only with approved isolated target; remediation and independent retest; final full standard/diff scans; human release gate. Read every applicable subordinate prompt before its work. Do not treat these milestones as complete based on this plan.
|
||||
|
||||
Open: approved ROE/staging isolation, complete trust-boundary/endpoint matrix, root policy decision, baseline/final scans, deep-scan allowance, full independent audit, provider/device/CI/deployment identity and live backup/restore. Security release recommendation: BLOCKED/NO-GO pending evidence. No new vulnerability has been asserted in Phase 00.
|
||||
|
||||
Next permitted action: read Phase 01 and the linked architecture topics, verify endpoint/actor boundaries from source, and prepare the policy proposal without writing an unapproved root policy. No user input is immediately required for that review.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Attachment ownership follow-through
|
||||
|
||||
2 November 2026. Source review plus bounded existing relational fixtures; not complete Phase 05, integrated security testing or deployed acceptance.
|
||||
|
||||
AttachmentsController.FindOwnedAttachmentAsync:42–47 includes JobApplication while selecting the raw child ID. JobTrackerContext:169–170 denies missing owners and filters JobApplication by CurrentUserId; the Attachment relation at 264–268 uses the parent foreign key. Attachment itself does not have a separate owner filter. Download, Rename and Delete all call this helper. ListForJob first checks the owned JobApplication exists, then limits child rows to that ID. Maintain these relationships; raw child queries without equivalent parent checks are not automatically safe.
|
||||
|
||||
AttachmentsControllerTests contains attribute/extension/size reflection tests, not cross-tenant behavioral proof. OwnershipGuardTests similarly checks helper presence. The stronger existing AttachmentConsistencyTests.Another_users_attachment_cannot_be_downloaded_renamed_or_deleted seeds a foreign job/file, clears tracking, checks three NotFound results and verifies the row/file remain.
|
||||
|
||||
Fresh targeted execution on the Phase 10 working tree: all 14 AttachmentConsistencyTests passed, zero failures/skips, exit 0, temporary SQLite and synthetic files only. Before execution, git diff between security and Phase 10 branches showed no JobTrackerApi/JobTrackerApi.Tests source difference. Existing Release assembly used --no-build/--no-restore. Evidence published and independently verified on Phase 10 at `db818e5ebd19eeedc05ae58dc3f7a908ce0e713d`, docs/redesign/phase-10/p10-04-evidence/attachment-ownership-and-storage.trx.gz. Uncompressed SHA256 `b589ad1139cb200d9de64b863d65e3304cea0230eda55d89476e5f79347fe84a`.
|
||||
|
||||
Result: selected local controller/storage behavior PASSED. Not an authenticated HTTP attack, complete negative list/upload/missing-owner matrix, MariaDB retest, production probe or final scan. Keep those gaps open. No new vulnerability or production exception is asserted; no backend fix was needed for these reviewed paths. Final integrated scan/testing stays deferred until relevant application changes are complete.
|
||||
@@ -0,0 +1,10 @@
|
||||
method,route,source,declared_auth,control_observed,sensitive_asset_or_effect,candidate_test_suite,audit_execution
|
||||
GET,/api/attachments/{jobId:int},AttachmentsController.cs:87,local scheme,parent owner-filtered existence check before child listing,attachment metadata,AttachmentConsistencyTests,source reviewed; negative list and HTTP NOT RUN
|
||||
GET,/api/attachments/download/{id:int},AttachmentsController.cs:103,local scheme,parent Include ownership filter and managed path checks,attachment bytes,AttachmentConsistencyTests,PASSED foreign-owner controller rejection; HTTP NOT RUN
|
||||
PATCH,/api/attachments/{id:int},AttachmentsController.cs:125,local scheme,parent Include ownership filter via shared helper,metadata and AI-use flag,AttachmentConsistencyTests,PASSED foreign-owner controller rejection; HTTP NOT RUN
|
||||
DELETE,/api/attachments/{id:int},AttachmentsController.cs:170,local scheme,parent Include ownership filter via shared helper,attachment removal,AttachmentConsistencyTests,PASSED foreign-owner controller rejection with row/file retained; HTTP NOT RUN
|
||||
GET,/api/billing/status,BillingController.cs:42,local scheme,method declares local authentication,entitlement status,BillingControllerTests,NOT RUN
|
||||
POST,/api/billing/checkout,BillingController.cs:58,local scheme,method declares local authentication; provider mocked only,checkout session,BillingControllerTests,NOT RUN
|
||||
POST,/api/billing/portal,BillingController.cs:104,local scheme,method declares local authentication; provider mocked only,billing portal,BillingControllerTests,NOT RUN
|
||||
POST,/api/billing/webhook,BillingController.cs:132,AllowAnonymous,signature verification and size limit; full binding audit pending,subscription entitlement,BillingControllerTests,NOT RUN
|
||||
PUT,/api/users/{id}/roles,UsersController.cs:142,Admin role at class,privilege transition review pending,account roles,UsersControllerTests,NOT RUN
|
||||
|
@@ -0,0 +1,13 @@
|
||||
# Root policy approval and resolver verification
|
||||
|
||||
3 November2026. Owner explicitly answered **"Approve policy creation and publication"** to the exact41-line SECURITY.md proposal and target in this chat. Approval includes validating the chain and committing/publishing on the security review branch; it does not approve a scan, charge, active testing or production action.
|
||||
|
||||
Target was reread and remained absent; HEAD was88bcd6d91c6823ffc6bbc6a6de176ab7769e729f and worktree was clean before creation. Applied text matches the approved candidate exactly after normal newline decoding. Policy LF SHA256: `4ec5365bdc1f84410b596b893463572b035f03d1260f51af722d1c32c8fa3eb3`.
|
||||
|
||||
Installed define-security-policy workflow: policy inventory and root/nearest-path guidance reviewed; both existing docs-only policies resolved inside the repository, regular files below1MiB. API had no inherited policy before the change. After creation the actual resolver exited0 for JobTrackerApi and job-tracker-ui with the new root policy, and for docs/cv-import with root plus its existing nearer policy. No inherited policy overwritten. Diff whitespace check passed. No application tests run for this Markdown-only change.
|
||||
|
||||
Exact proposal retained through Codex Security managed standalone artifact storage: `artifacts/root-policy-proposal.md`, artifact SHA256 `5d00af57cfa55de2792218916fd9cf646b470d821db6e8afee5c59c76dba116b`, at `C:\Users\Connor\.codex\state\plugins\codex-security\scans\Job-tracker\artifacts-ad2afb630ff68e10e32f349b87541ffb5778071babb98965362c085936a3f385\artifacts\root-policy-proposal.md`. Persistent readback succeeded. This is a standalone document collection, not a scan ID or result.
|
||||
|
||||
No new finding exclusion, risk acceptance or severity downgrade. Canonical-profile, tenant, revision, parser/file, AI-consent, provider and recovery invariants remain review requirements, not assertions that all controls already pass. No secret values or private user content read/exported. Source-security and final integrated acceptance remain open.
|
||||
|
||||
Next: reconcile the intended immutable integration revision before a baseline scan, finish capability/cost/scope preflight and record actual results. The older offline audit branch is not a final scan of A3 UI changes. Deep allowance and isolated staging remain distinct protected decisions; final integrated scanning follows relevant application changes.
|
||||
Reference in New Issue
Block a user