Security Dossier — APT Repo Manager¶
Classification: Confidential — CISO / Security Team Use Only
Version: 1.0
Date: 2026-05-12
Audience: CISO, Security Officers, Security Engineering Team
Table of Contents¶
- Security Overview
- Authentication and Identity Management
- Access Control (RBAC)
- Package Security Pipeline
- Vulnerability Management (CVE)
- SBOM and Software Traceability
- Audit Trail and Logging
- Infrastructure Hardening
- HTTP Security Headers
- Known Limitations and Open Issues
- Compliance Checklist
1. Security Overview¶
APT Repo Manager is an enterprise-grade Debian package repository management platform (APT format). It provides full control over the software supply chain, from package intake to distribution to target systems.
Security Posture¶
The platform is built on the following principles:
- Defense in depth: every incoming package traverses a sequential, independent multi-stage control pipeline (antivirus, CVE, GPG signature, integrity).
- Least privilege: five distinct roles with precisely scoped permission boundaries.
- Separation of duties: CVE remediation decisions are reserved for the CISO/security team; operators cannot self-approve vulnerable packages.
- Full traceability: every sensitive action is recorded in append-only JSONL audit files.
- Regulatory alignment: NIS2, ANSSI SecNumCloud, GDPR.
Core Components¶
| Component | Technology | Role |
|---|---|---|
| Backend API | FastAPI (Python 3.11) | Business logic, authentication, security pipeline |
| Database | SQLite (PostgreSQL recommended for production) | Users, packages, tokens, CVE records |
| Antivirus | ClamAV (dedicated container) | Malware detection on every upload |
| CVE Scanner | Grype (Anchore) | Known vulnerability analysis |
| Frontend | React + Nginx | CISO/operator interface |
| Storage | Docker volume /repos | Packages, manifests, audit logs, GPG keyrings |
2. Authentication and Identity Management¶
2.1 Local Authentication¶
- Password storage: bcrypt hashing via
passlib[bcrypt]. No plaintext passwords stored anywhere. - Password policy (enforced server-side at the API layer):
- Minimum length: 8 characters
- Requirement: at least 1 uppercase letter AND at least 1 digit or special character
- Server-side enforcement only — cannot be bypassed via the API
- Password reset: reset tokens are stored as SHA-256 hashes only — never in plaintext in the database.
- Account status:
is_activefield verified on every authenticated request. Deactivating an account immediately invalidates all active sessions.
2.2 JWT Tokens (User Sessions)¶
- Algorithm: HS256
- Token lifetime: 60 minutes (not configurable without code modification)
- Secret key:
JWT_SECRET_KEYvalidated at startup. If the default value or an empty value is detected in production (ENV=production), the application refuses to start. - Per-request verification: user active status is checked on every request, not only at token creation time.
- Known limitation: no JWT revocation mechanism or blacklist. A valid token remains functional until natural expiry (60 min) even after explicit logout. See Section 10.
2.3 API Tokens (CI/CD)¶
- Format:
repod_prefix + cryptographically secure random suffix - Storage: SHA-256 hash only, never in plaintext
- Expiry: configurable per token (optional)
- Revocation: immediate, by administrator or token owner
- Use case: designed for non-interactive CI/CD pipelines
2.4 LDAP / Active Directory (Optional)¶
- Library:
ldap3 - TLS:
verify_cert=Trueby default (LDAP server certificate verification enabled) - Auto-provisioning: on first successful LDAP login, a local account is created with a random, non-usable local password (LDAP authentication is then the only valid mechanism)
- Configuration: URL, bind DN, search base, user filter — all configurable via the admin interface
- Bind password masking: LDAP bind passwords are masked in GET
/settingsresponses
2.5 Rate Limiting¶
| Endpoint | Limit |
|---|---|
Authentication (/auth/*) |
10 requests / minute |
| Package upload | 20 requests / minute |
| Import / fetch | 10 requests / minute |
| Batch operations | 5 requests / minute |
| Repository sync | 3 requests / minute |
3. Access Control (RBAC)¶
The platform implements Role-Based Access Control (RBAC) with 5 distinct privilege levels.
3.1 Permission Matrix¶
| Permission | admin | maintainer | uploader | auditor | reader |
|---|---|---|---|---|---|
| User management | Yes | No | No | No | No |
| Settings modification | Yes | No | No | No | No |
| Package upload | Yes | Yes | Yes | No | No |
| Package import | Yes | Yes | Yes | No | No |
| Package promotion | Yes | Yes | No | No | No |
| Package deletion | Yes | Yes | No | No | No |
| Repository sync | Yes | Yes | No | No | No |
| CVE decision (approve/reject) | Yes | No | No | No | No |
| Audit log access | Yes | Yes | No | Yes | No |
| Package read access | Yes | Yes | Yes | Yes | Yes |
| SBOM export | Yes | Yes | No | Yes | No |
| API token management | Yes (all) | Yes (own) | Yes (own) | No | No |
3.2 Role Descriptions¶
admin: full access to all platform capabilities. The only role authorized to create/modify/delete user accounts, change system configuration, and approve or reject CVE decisions in the CISO review queue.
maintainer: full package lifecycle management (upload, import, promotion, deletion, sync). Read access to audit logs. Cannot manage users or approve CVEs.
uploader: can upload and import packages only. Cannot promote, delete, or sync. Appropriate for CI/CD pipelines requiring minimal access.
auditor: read-only access to packages and audit logs. Dedicated to compliance teams and external auditors. No write operations of any kind.
reader: read-only access to packages only. No access to audit logs. Suitable for passive repository consumers.
4. Package Security Pipeline¶
Every incoming package (upload or import) is subjected to a 7-stage sequential security pipeline before any publication.
4.1 Pipeline Diagram¶
Package received
|
v
[1] Format validation (dpkg-deb)
|-- FAIL --> Immediate rejection (HTTP 400)
v
[2] SHA-256 provenance check
|-- MISMATCH --> Immediate rejection
v
[3] ClamAV antivirus scan
|-- VIRUS DETECTED --> Quarantine + block
v
[4] Grype CVE scan
|-- CRITICAL/HIGH (policy=block) --> Quarantine
|-- CRITICAL/HIGH (policy=review) --> pending_review (CISO queue)
|-- MEDIUM/LOW (policy=warn) --> Published with warning flag
v
[5] GPG signature verification
|-- INVALID --> Warning (non-blocking)
v
[6] Dependency availability check
|-- MISSING DEPS --> Warning (non-blocking)
v
[7] EPSS enrichment + CISA KEV check
v
Package published to repository
4.2 Stage-by-Stage Description¶
Stage 1 — Format Validation (dpkg-deb)
Verifies the structural integrity of the .deb file using dpkg-deb --info. Any malformed, truncated, or non-Debian-compliant file is rejected with HTTP 400. This stage protects against file smuggling attempts disguised as Debian packages.
Stage 2 — SHA-256 Provenance Check
The SHA-256 hash of the uploaded package is compared against the hash recorded in the source repository's Packages.gz index. Guarantees that the package has not been tampered with between its source and the platform. Any hash mismatch results in immediate rejection.
Stage 3 — ClamAV Antivirus Scan
The package is submitted to ClamAV (signature database updated daily). Any malware detection triggers quarantine placement and publication blocking. The quarantine directory is isolated from the active repository and accessible only to administrators.
Stage 4 — Grype CVE Scan
Grype analyzes the package SBOM and cross-references it against NVD, GitHub Advisory Database, and CISA KEV. The response to each finding is determined by the policy configured per severity level:
| Severity | Policy | Behavior |
|---|---|---|
| Critical | block | Rejected to quarantine, never published |
| Critical | review | pending_review, mandatory CISO queue |
| High | block | Rejected to quarantine |
| High | review | pending_review, CISO queue |
| Medium | warn | Published with warning flag |
| Low | allow | Published without restriction |
Policies are configurable by administrators via the interface.
Stage 5 — GPG Signature Verification
Verifies that the package is signed with a trusted GPG key. This stage is non-blocking: a package without a valid signature is published but marked unsigned. The CISO can configure a strict policy (block if unsigned) via platform settings.
Stage 6 — Dependency Availability Check
Verifies that all dependencies declared in the package Depends: field are available in the repository. A package with missing dependencies generates a warning but is published. This prevents introducing broken packages while not blocking legitimate workflows.
Stage 7 — EPSS Enrichment + CISA KEV Check
For each CVE identified in Stage 4:
- EPSS (Exploit Prediction Scoring System): probability of exploitation in the next 30 days, sourced from FIRST.org.
- CISA KEV (Known Exploited Vulnerabilities): checks whether the CVE is actively exploited according to the CISA catalog.
This data enriches the vulnerability report presented to the CISO for prioritization.
5. Vulnerability Management (CVE)¶
5.1 CISO Review Queue (pending_review)¶
Packages where at least one CVE triggers the review policy transition to pending_review status. They are visible in the CISO interface but are not accessible to repository consumers. The CISO has two available actions:
- Approve: the package is promoted to publication. Justification is mandatory and recorded in the audit trail.
- Reject: the package is moved to quarantine. Justification is mandatory and recorded.
5.2 Decision Workflow¶
pending_review
|
|-- CISO: Approve (justification required) --> Published
|-- CISO: Reject (justification required) --> Quarantine
Only the admin role can make these decisions. The maintainer role can read the queue but cannot approve.
5.3 SLA by Severity¶
| Severity | Default SLA | Configurable |
|---|---|---|
| Critical | 0 days (immediate decision required) | Yes |
| High | 30 days | Yes |
| Medium | 90 days | Yes |
| Low | No SLA | Yes |
SLA breaches generate alerts in the administration interface. SLAs are configurable by the administrator via platform settings.
5.4 Contextual Enrichment¶
Each CVE presented to the CISO includes: - CVSS v3 score (base score + attack vector) - EPSS score (30-day exploitation probability) - CISA KEV catalog membership - Affected package, version, available fix - Previous decision justification (if applicable)
6. SBOM and Software Traceability¶
6.1 Supported Formats¶
| Standard | Version | Body |
|---|---|---|
| CycloneDX | 1.5 | OWASP |
| SPDX | 2.3 | ISO/IEC 5962:2021 |
6.2 SBOM Contents¶
Each generated SBOM contains: - Complete component inventory of the package (direct and transitive dependencies) - Associated CVE identifiers and their status (suppressed, in_triage, exploitable) - SHA-256 hash of each component - Vendor metadata, version, SPDX license identifier - Generation timestamp and timestamp of the last CVE scan
6.3 Regulatory Alignment¶
The SBOM addresses requirements from: - NIS2 (EU 2022/2555): Article 21 — software inventory, vulnerability management - ANSSI SecNumCloud: software inventory, component traceability - Executive Order 14028 (US, for reference): SBOM for delivered software
6.4 Export¶
SBOM export is available via:
- Web interface (roles: admin, maintainer, auditor)
- REST API: GET /api/packages/{id}/sbom?format=cyclonedx or ?format=spdx
7. Audit Trail and Logging¶
7.1 Format and Storage¶
- Format: JSONL (JSON Lines) — one event per line
- Organization: one file per day —
/repos/audit/YYYY-MM-DD.jsonl - Access: read-only access restricted to roles
admin,maintainer,auditor - Write mode: append-only. No modification or deletion API exists.
- Retention: configurable (default: 90 days). Rotation of expired files is handled automatically.
7.2 Event Structure¶
{
"timestamp": "2026-05-12T14:32:01.412Z",
"event": "UPLOAD",
"user": "john.doe",
"role": "maintainer",
"ip": "10.0.1.42",
"details": {
"package": "libssl3_3.0.2-0ubuntu1_amd64.deb",
"sha256": "a3f1...",
"clamav": "clean",
"grype_findings": 2,
"status": "pending_review"
}
}
7.3 Logged Event Types¶
| Event | Trigger |
|---|---|
LOGIN_SUCCESS |
Successful login (includes source IP) |
LOGIN_FAILURE |
Failed login attempt (includes source IP and reason) |
USER_CREATE |
User account creation |
USER_UPDATE |
Account modification (role, status, email) |
USER_DELETE |
Account deletion |
PASSWORD_CHANGE |
User-initiated password change |
PASSWORD_RESET |
Password reset (admin-initiated or via reset token) |
UPLOAD |
Package upload (pipeline results included) |
DELETE |
Package deletion |
PROMOTE |
Package promotion to another repository |
IMPORT |
Import from an external repository |
SYNC |
Repository synchronization |
SETTINGS_CHANGE |
Configuration modification (modified field logged) |
GPG_GENERATE |
GPG key pair generation |
CVE_APPROVE |
Approval of a pending_review package (with justification) |
CVE_REJECT |
Rejection of a pending_review package (with justification) |
TOKEN_CREATE |
API token creation |
TOKEN_REVOKE |
API token revocation |
7.4 GDPR Considerations¶
Audit logs include user IP addresses, which constitute personal data under GDPR. Key points:
- Retention is configurable and must be aligned with the organization's internal data retention policy.
- No other personal data is present in logs (no passwords, no session tokens).
- Legal basis for processing: legitimate interest / NIS2 legal obligation (security of information systems).
8. Infrastructure Hardening¶
8.1 Containerization (Docker)¶
| Measure | Status | Detail |
|---|---|---|
| Docker socket not mounted | Applied | The backend container has no access to /var/run/docker.sock |
| Source code not mounted in production | Applied | Only the /repos volume is mounted in production |
| GPG via shared volume | Applied | /repos/gnupg shared between backend and GPG service, without Docker socket access |
| Non-root user | Applied | Backend process runs under a dedicated non-root UID |
| Minimal base image | Recommended | Use a Debian slim or distroless base image |
8.2 FastAPI Application¶
| Measure | Status | Detail |
|---|---|---|
| Swagger UI disabled in production | Applied | ENV=production → /docs and /redoc return 404 |
| Hot-reload disabled | Applied | uvicorn starts without --reload in production |
| Worker count | Applied | 2 uvicorn workers in production |
| JWT_SECRET_KEY validation | Applied | Application refuses to start if default/missing value detected in production |
| Secret masking in /settings | Applied | SMTP and LDAP bind passwords masked (***) in GET responses |
| Trusted proxies | Configurable | TRUSTED_PROXIES env var for the list of authorized proxy IPs |
8.3 Network¶
| Measure | Status | Detail |
|---|---|---|
| HTTPS in production | Not included | Delegated to reverse proxy (see REVERSE_PROXY.md) |
| Backend port exposure | Open issue | Port 8000 exposed on 0.0.0.0 without reverse proxy — see Section 10 |
| Docker network isolation | Recommended | Use dedicated Docker networks to isolate components |
8.4 GPG Key Management¶
- GPG key pair generation for repository signing is integrated into the administration interface.
- Keys are stored in
/repos/gnupgwith standard GnuPG restrictive permissions. - The public key is automatically exported to the repository, enabling verification by APT clients.
9. HTTP Security Headers¶
The following security headers are configured on the frontend Nginx server.
| Header | Configured Value | Purpose |
|---|---|---|
X-Frame-Options |
SAMEORIGIN |
Clickjacking protection |
X-Content-Type-Options |
nosniff |
MIME type sniffing prevention |
X-XSS-Protection |
1; mode=block |
Legacy XSS protection (older IE/Edge) |
Referrer-Policy |
strict-origin-when-cross-origin |
Referrer information leakage control |
Content-Security-Policy |
default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self' |
Content source restriction |
Permissions-Policy |
camera=(), microphone=(), geolocation=(), payment=() |
Browser sensitive API disablement |
9.1 Known Issue: CSP unsafe-inline¶
The 'unsafe-inline' directive is present in both script-src and style-src. This configuration is due to React's use of inline styles and inline event handlers. It weakens CSP protection against injected XSS attacks. Migration to a nonce-based CSP is planned for version 3 (see Section 10).
10. Known Limitations and Open Issues¶
This section documents current known platform limitations, their risk level, and recommended compensating controls.
10.1 No JWT Revocation / Blacklist¶
| Attribute | Value |
|---|---|
| Risk | Medium |
| Description | JWT tokens have a 60-minute lifetime. After explicit logout or account deactivation, the token remains technically valid until expiry. |
| Impact | A stolen session token remains exploitable for up to 60 minutes, even if the associated account is deactivated. |
| Compensating Control | The 60-minute window limits exploitation exposure. Account deactivation is verified on every request, blocking tokens associated with disabled accounts at the request level. |
| Planned Fix | Redis-based token blacklist implementation in v2.x |
10.2 No HTTPS in Default Configuration¶
| Attribute | Value |
|---|---|
| Risk | High (if deployed without reverse proxy) |
| Description | The default configuration does not terminate TLS at the platform level. |
| Impact | Client-server communications are unencrypted without a reverse proxy. |
| Compensating Control | Mandatory deployment behind a TLS-terminating reverse proxy (nginx, Traefik, HAProxy). See REVERSE_PROXY.md. |
| Status | Native TLS integration not planned (reverse proxy is the standard production pattern) |
10.3 Backend Port Exposed on 0.0.0.0¶
| Attribute | Value |
|---|---|
| Risk | Medium (without reverse proxy) |
| Description | Backend port 8000 is bound to all network interfaces. |
| Impact | Without a reverse proxy or firewall rule, the API is directly reachable, bypassing the frontend's security headers. |
| Compensating Control | Apply iptables/nftables rules restricting port 8000 access to reverse proxy IPs only. |
10.4 Content-Security-Policy with unsafe-inline¶
| Attribute | Value |
|---|---|
| Risk | Low (internal interface, no user-controlled script input) |
| Description | The CSP allows unsafe-inline for scripts and styles. |
| Impact | Reduced protection against injected XSS payloads. |
| Planned Fix | Migration to nonce-based CSP in v3 |
10.5 Automatic LDAP Account Provisioning¶
| Attribute | Value |
|---|---|
| Risk | Low |
| Description | A local account is automatically created on the first successful LDAP login, with a random, non-usable local password. |
| Impact | Accounts can be created without an explicit administrator action. |
| Compensating Control | The administrator must manually assign a role (auto-provisioned accounts have no role by default and thus no permissions). |
11. Compliance Checklist¶
11.1 NIS2 (EU 2022/2555)¶
| NIS2 Requirement | Status | Implementation |
|---|---|---|
| Security policy for network and information systems | Partial | RBAC, security pipeline — formal written policy required at org level |
| Incident handling | Partial | Complete audit trail — internal incident response procedure required |
| Business continuity | Not covered | To be defined at organization level |
| Supply chain security | OK | CVE pipeline, SBOM, GPG signing, antivirus |
| Network and information systems security | Partial | HTTP security headers — TLS delegated to reverse proxy |
| Access control | OK | 5-role RBAC, JWT, MFA not included |
| Encryption | Partial | Passwords hashed, TLS via reverse proxy |
| Vulnerability management | OK | Grype, CISO review queue, configurable SLA, EPSS, CISA KEV |
| Logging and monitoring | OK | JSONL audit trail, configurable retention, 18 event types |
| Security testing | Not covered | To be scheduled (penetration testing, code review) |
11.2 ANSSI SecNumCloud¶
| Requirement | Status | Implementation |
|---|---|---|
| Software inventory | OK | CycloneDX 1.5 + SPDX 2.3 SBOM per package |
| Audit logs | OK | Append-only JSONL, configurable retention |
| Access control | OK | RBAC, least privilege |
| Environment separation | Partial | Docker containers — network isolation to be reinforced |
| Data encryption at rest | Not covered | /repos volume unencrypted by default — to be managed at OS/infrastructure level |
| Data encryption in transit | Partial | Delegated to reverse proxy |
| Key management | Partial | Integrated GPG, validated JWT secret — HSM not included |
11.3 GDPR¶
| Requirement | Status | Implementation |
|---|---|---|
| Data minimization | OK | Only email, role, and IP address collected |
| Data retention | Configurable | Audit log retention configurable (default 90 days) — align with internal policy |
| Data security | OK | bcrypt hashing, TLS (reverse proxy), restricted access |
| Records of processing activities | Not covered | To be documented by the organization |
| Data subject rights procedure | Not covered | To be defined by the organization |
11.4 Global Summary¶
| Domain | Overall Status |
|---|---|
| Authentication & identity | OK |
| Access control | OK |
| Package security | OK |
| Vulnerability management | OK |
| SBOM & traceability | OK |
| Logging & audit | OK |
| Infrastructure hardening | Partial |
| Encryption & TLS | Partial |
| NIS2 compliance | Partial |
| SecNumCloud compliance | Partial |
| GDPR compliance | Partial |
Vulnerability Reporting¶
Security vulnerabilities must be reported through a confidential channel:
Contact: security@[organization]
Channel: Do not use the public issue tracker for security vulnerabilities.
Target response time: 72 hours for acknowledgment, 30 days for remediation (High/Critical vulnerabilities).
Document generated on 2026-05-12 — APT Repo Manager v1.x — Restricted to CISO / Security Team