@atlasnomos/atlas 1.1.14 → 10.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +113 -57
- package/atlas.js +0 -1
- package/bin/atlas +1 -1
- package/config/sentinel-keys.json +15 -0
- package/config/trust-boundaries.json +64 -0
- package/index.js +10 -0
- package/package.json +7 -3
- package/src/bridge/RingBridge.js +0 -2
- package/src/core/SecretRedactor.js +81 -1
- package/src/enforcement/RuntimeSandbox.js +155 -26
- package/src/interface/cli/commands/BuildCommand.js +68 -35
- package/src/kernel/automation/AutomationRegistry.js +159 -0
- package/src/kernel/automation/AutomationSchema.js +109 -0
- package/src/kernel/automation/AutomationVerifier.js +135 -0
- package/src/kernel/automation/LastRunLedger.js +220 -0
- package/src/kernel/boot/AgentProcess.js +0 -1
- package/src/kernel/boot/Bootstrap.js +105 -0
- package/src/kernel/boot/SystemInitializer.js +6 -1
- package/src/kernel/constitution/SentinelInterface.js +180 -3
- package/src/kernel/constitution/invariants/automation.invariants.js +126 -0
- package/src/kernel/constitution/invariants/frequency.invariants.js +77 -0
- package/src/kernel/constitution/invariants/registry.invariants.js +70 -0
- package/src/kernel/crypto/DirectoryHasher.js +101 -0
- package/src/kernel/io/AuditSink.js +95 -1
- package/src/kernel/io/DecisionTrace.js +19 -0
- package/src/kernel/io/FeedbackLearner.js +6 -1
- package/src/kernel/io/HashChainedLog.js +57 -3
- package/src/kernel/io/TelemetryService.js +6 -1
- package/src/kernel/modes/ActiveMode.js +158 -0
- package/src/kernel/modes/dev.js +33 -0
- package/src/kernel/modes/fortress.js +33 -0
- package/src/kernel/modes/prod.js +41 -0
- package/src/kernel/security/ConfigDecryptor.js +61 -7
- package/src/kernel/sentinel/KeyRegistry.js +399 -0
- package/src/monitoring/CostTracker.js +70 -0
package/README.md
CHANGED
|
@@ -1,96 +1,152 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 🦅 ATLAS — The Governance Kernel for AI Agents
|
|
2
2
|
|
|
3
|
-
[](
|
|
5
|
-
[](https://atlasnomos.com)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](CAP/README.md)
|
|
6
6
|
|
|
7
|
-
> **
|
|
7
|
+
> **v10.0.0 — KERNEL PROD** • [AGPL-3.0 License](LICENSE)
|
|
8
8
|
|
|
9
|
-
ATLAS is
|
|
9
|
+
ATLAS is a **Ring-0 Governance Kernel** for autonomous AI operations. It sits between an Agent and the World, strictly enforcing institutional policies, audit logging, and fail-close security boundaries.
|
|
10
|
+
|
|
11
|
+
**ATLAS is not a wrapper.** It is an immutable compliance hypervisor that panics and halts execution upon violation.
|
|
10
12
|
|
|
11
13
|
---
|
|
12
14
|
|
|
13
|
-
##
|
|
15
|
+
## 🏛️ Governance Status: PROD READY
|
|
16
|
+
|
|
17
|
+
As of Q1 2026, ATLAS v10 is fully hardened and certified for production.
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
| Component | Status | Guarantee |
|
|
20
|
+
|-----------|--------|-----------|
|
|
21
|
+
| **Kernel** | 🟢 **Hardened** | Fail-Close, Ring-Isolated |
|
|
22
|
+
| **Execution** | 🟢 **Deterministic** | Bit-for-bit Replay, Unforgeable Logs |
|
|
23
|
+
| **Trust Root** | 🟢 **Sealed** | Config Hashed at Boot, Signed by Sentinel |
|
|
24
|
+
| **Sandbox** | 🟢 **Isolated** | No Network, Mocked Time/Entropy |
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
👉 **[View Official Governance Reports (CAP)](CAP/README.md)**
|
|
18
27
|
|
|
19
28
|
---
|
|
20
29
|
|
|
21
|
-
##
|
|
30
|
+
## 🏗️ Architecture: The Ring Model
|
|
31
|
+
|
|
32
|
+
ATLAS employs a strictly layered "Ring" architecture to isolate decision-making from execution.
|
|
33
|
+
|
|
34
|
+
1. **Ring-0 (The Kernel)**:
|
|
35
|
+
* **The Constitution**: Immutable invariants (Fail-Close).
|
|
36
|
+
* **The Sentinel**: Cryptographic authority (Ed25519 Signatures).
|
|
37
|
+
* **The Log**: Hash-chained, framed, atomic audit trails.
|
|
38
|
+
* *Nothing in Ring-0 can be bypassed.*
|
|
22
39
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
-
|
|
40
|
+
2. **Ring-1 (The Bridge)**:
|
|
41
|
+
* Safe I/O handling.
|
|
42
|
+
* Policy translation.
|
|
43
|
+
|
|
44
|
+
3. **Ring-2 (The Agent)**:
|
|
45
|
+
* LLM Cognition (Untrusted).
|
|
46
|
+
* The Agent *proposes* actions; the Kernel *approves* or *denies* them.
|
|
28
47
|
|
|
29
48
|
---
|
|
30
49
|
|
|
31
|
-
##
|
|
50
|
+
## 🛡️ Key Features
|
|
32
51
|
|
|
33
|
-
###
|
|
34
|
-
|
|
35
|
-
- **Windows**: `atlas-installer-win-v10.exe`
|
|
36
|
-
- Deploys the Governance Enclave to `%LOCALAPPDATA%\ATLAS`.
|
|
37
|
-
- Automatically configures your environment and hardware-aware encryption.
|
|
52
|
+
### 🔒 Deny-by-Default
|
|
53
|
+
If the Kernel cannot prove an action is safe and authorized, it **STOPS**. There are no warnings in PROD. There are no "soft fails".
|
|
38
54
|
|
|
39
|
-
###
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
*
|
|
55
|
+
### 🔎 Deterministic Replay
|
|
56
|
+
Every execution is mathematically deterministic.
|
|
57
|
+
* **Seeding**: Entropy is derived from `SHA256(Input + Code)`.
|
|
58
|
+
* **Time**: Mocked and frozen relative to the seed.
|
|
59
|
+
* **Audit**: An auditor can replay the log and get the exact same result.
|
|
60
|
+
|
|
61
|
+
### ✍️ Sentinel Authority
|
|
62
|
+
Every high-risk action requires a **Sentinel Signature**.
|
|
63
|
+
* The Sentinel is an external authority (Policy Server / HSM).
|
|
64
|
+
* ATLAS verifies the signature against a local Trusted Key Registry.
|
|
65
|
+
* The Kernel refuses to boot if the Registry is missing or tampered.
|
|
66
|
+
|
|
67
|
+
### ⚡ AURORA+ (Automation Support)
|
|
68
|
+
AURORA+ enables **governed automation** via Sentinel-signed delegation.
|
|
69
|
+
* **Not a scheduler**: Automation is delegated authority, not cron jobs.
|
|
70
|
+
* **PROD-only**: Completely blocked in DEV mode.
|
|
71
|
+
* **Kernel-enforced**: Frequency, cost, and scope limits enforced at Ring-0.
|
|
72
|
+
* **Replay-verifiable**: All executions are hash-chained and deterministic.
|
|
73
|
+
|
|
74
|
+
| Property | Guarantee |
|
|
75
|
+
|----------|-----------|
|
|
76
|
+
| Authority Source | Sentinel-signed grants |
|
|
77
|
+
| Frequency Limit | Kernel-enforced (INV-AUTO-FREQ-001) |
|
|
78
|
+
| Scope Limit | Panic on violation |
|
|
79
|
+
| Revocation | Snapshot at boot |
|
|
80
|
+
|
|
81
|
+
👉 **[AURORA+ User Guide](docs/AURORA_USER_GUIDE.md)** • **[Technical Reports](REPORTS/AURORA_PLUS/)**
|
|
44
82
|
|
|
45
83
|
---
|
|
46
84
|
|
|
47
|
-
##
|
|
85
|
+
## � Modes: DEV vs PROD
|
|
48
86
|
|
|
49
|
-
|
|
50
|
-
Ensure your provider key is available (e.g., OpenRouter):
|
|
51
|
-
```powershell
|
|
52
|
-
$env:OPENROUTER_API_KEY="your-key-here"
|
|
53
|
-
```
|
|
87
|
+
ATLAS operates in two distinct modes. A `DEV` success does **not** guarantee `PROD` success.
|
|
54
88
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
89
|
+
| Feature | 🟡 DEV MODE | 🟢 PROD MODE |
|
|
90
|
+
| :--- | :--- | :--- |
|
|
91
|
+
| **Enforcement** | Advisory (Warn Log) | **Fail-Close** (Panic/Halt) |
|
|
92
|
+
| **Sentinel** | Optional / Bypassed | **MANDATORY** (Hard Dependency) |
|
|
93
|
+
| **Hardware** | Simulated | **MANDATORY** (TPM/HSM) |
|
|
94
|
+
| **Config Integrity** | Warn on Change | **PANIC** on Change |
|
|
95
|
+
| **Symlinks** | Allowed | **PANIC** (Security Violation) |
|
|
96
|
+
| **Log Durability** | Standard | **Atomic / Fsync** |
|
|
60
97
|
|
|
61
|
-
###
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
98
|
+
### 🟢 PROD Mode (Production)
|
|
99
|
+
* **Role**: Governance Hypervisor.
|
|
100
|
+
* **Behavior**: Deny-by-Default. If the Kernel suspects *anything* is wrong (network flake, config drift, bad signature), it halts execution immediately.
|
|
101
|
+
* **Use Case**: Live operations, high-value asset handling.
|
|
102
|
+
|
|
103
|
+
### 🟡 DEV Mode (Development)
|
|
104
|
+
* **Role**: Rapid Iteration Sandbox.
|
|
105
|
+
* **Behavior**: Permissive. Allows `ATLAS_DEV_BYPASS` to skip Sentinel, uses mock time/randomness, and tolerates config changes.
|
|
106
|
+
* **Use Case**: Unit testing, local debugging.
|
|
107
|
+
|
|
108
|
+
> **CRITICAL**: Never treat `DEV` mode as a security boundary. It is a velocity tool.
|
|
66
109
|
|
|
67
110
|
---
|
|
68
111
|
|
|
69
|
-
##
|
|
112
|
+
## �📦 Documentation
|
|
70
113
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
114
|
+
All governance documentation is centralized in the **Compliance Assurance Package (CAP)**.
|
|
115
|
+
|
|
116
|
+
* **[System Status](CAP/01_SYSTEM_STATUS.md)**: Operational health.
|
|
117
|
+
* **[PROD Certification](CAP/03_PROD_CERTIFICATION.md)**: Detailed security guarantees.
|
|
118
|
+
* **[DEV vs PROD](CAP/04_DEV_VS_PROD_COMPARISON.md)**: Critical environment differences.
|
|
119
|
+
* **[Ops Runbook](CAP/07_OPERATIONAL_READINESS.md)**: Incident response and key handling.
|
|
74
120
|
|
|
75
121
|
---
|
|
76
122
|
|
|
77
|
-
##
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
123
|
+
## 🚀 Quick Start (DEV Mode)
|
|
124
|
+
|
|
125
|
+
> **WARNING**: `DEV` mode is for experimentation only. It bypasses critical security checks.
|
|
126
|
+
|
|
127
|
+
### 1. Install
|
|
128
|
+
```bash
|
|
129
|
+
npm install -g @atlasnomos/atlas
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 2. Check Health
|
|
133
|
+
```bash
|
|
134
|
+
atlas doctor
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 3. Run a Task
|
|
138
|
+
```bash
|
|
139
|
+
atlas build "Analyze this codebase for security flaws"
|
|
140
|
+
```
|
|
81
141
|
|
|
82
142
|
---
|
|
83
143
|
|
|
84
144
|
## 📄 License
|
|
85
145
|
|
|
86
146
|
ATLAS is licensed under the [GNU Affero General Public License v3.0](LICENSE).
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
- ✅ You can modify ATLAS
|
|
91
|
-
- ✅ You can distribute ATLAS
|
|
92
|
-
- ⚠️ If you run a modified version as a network service, you must make the source code available to users
|
|
93
|
-
- ⚠️ Derivative works must also be licensed under AGPL-3.0
|
|
147
|
+
* **Commercial Use**: Allowed.
|
|
148
|
+
* **Modification**: Allowed (must stay open source if networked).
|
|
149
|
+
* **Distribution**: Allowed.
|
|
94
150
|
|
|
95
151
|
See [LICENSE](LICENSE) for full terms.
|
|
96
152
|
|
package/atlas.js
CHANGED
|
@@ -158,7 +158,6 @@ const { ModelsCommand } = require('./src/interface/cli/commands/ModelsCommand');
|
|
|
158
158
|
dispatcher.register('unsafe', new UnsafeCommand());
|
|
159
159
|
dispatcher.register('sync', new SyncCommand());
|
|
160
160
|
dispatcher.register('config', new ConfigCommand());
|
|
161
|
-
dispatcher.register('config', new ConfigCommand());
|
|
162
161
|
dispatcher.register('providers', new ProvidersCommand());
|
|
163
162
|
dispatcher.register('help', new HelpCommand());
|
|
164
163
|
dispatcher.register('models', new ModelsCommand());
|
package/bin/atlas
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"keys": [
|
|
4
|
+
{
|
|
5
|
+
"key_id": "sentinel-prod-01",
|
|
6
|
+
"public_key": "a222cb32f6f2a21696144fa63cf36f148336dfc8bafc3bafdd782d90eaf99fcc",
|
|
7
|
+
"algorithm": "ed25519",
|
|
8
|
+
"status": "ACTIVE",
|
|
9
|
+
"added_at": "2026-01-24T18:00:00Z",
|
|
10
|
+
"valid_from": "2026-01-24T18:00:00Z",
|
|
11
|
+
"valid_until": "2030-01-01T00:00:00Z"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"registry_hash": "PROD_SEALED"
|
|
15
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"updated": "2025-12-28T21:48:00Z",
|
|
4
|
+
"boundaries": {
|
|
5
|
+
"local": {
|
|
6
|
+
"segments": [
|
|
7
|
+
"127.0.0.1",
|
|
8
|
+
"::1"
|
|
9
|
+
],
|
|
10
|
+
"hardware_anchors": {
|
|
11
|
+
"tpm": {
|
|
12
|
+
"pcr_registry": [
|
|
13
|
+
9,
|
|
14
|
+
11,
|
|
15
|
+
12,
|
|
16
|
+
13,
|
|
17
|
+
14
|
|
18
|
+
],
|
|
19
|
+
"status": "MANDATORY"
|
|
20
|
+
},
|
|
21
|
+
"hsm": {
|
|
22
|
+
"type": "YubiHSM-2",
|
|
23
|
+
"path": "/dev/ttyACM0",
|
|
24
|
+
"status": "OPTIONAL_SIMULATED"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"filesystem": {
|
|
28
|
+
"root": "c:\\Users\\rianz\\ATLAS NOMOS\\atlas",
|
|
29
|
+
"protected_dirs": [
|
|
30
|
+
".atlas",
|
|
31
|
+
"src/kernel"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"external": {
|
|
36
|
+
"sentinel": {
|
|
37
|
+
"endpoint": "http://localhost:8000",
|
|
38
|
+
"protocol": "HTTPS_REQUIRED_PROD",
|
|
39
|
+
"allowed_ports": [
|
|
40
|
+
80,
|
|
41
|
+
443,
|
|
42
|
+
8000
|
|
43
|
+
],
|
|
44
|
+
"certificate_pinning": {
|
|
45
|
+
"enabled": true,
|
|
46
|
+
"expected_fingerprint": "98a65438991bf1cdbed0d1036199725b"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"llm_providers": {
|
|
50
|
+
"allowed_domains": [
|
|
51
|
+
"openrouter.ai",
|
|
52
|
+
"api.anthropic.com",
|
|
53
|
+
"api.openai.com"
|
|
54
|
+
],
|
|
55
|
+
"protocol": "HTTPS_ONLY"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"policy": {
|
|
60
|
+
"mismatched_endpoint": "PANIC",
|
|
61
|
+
"protocol_downgrade": "PANIC",
|
|
62
|
+
"unknown_external_access": "BLOCK"
|
|
63
|
+
}
|
|
64
|
+
}
|
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlasnomos/atlas",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.1",
|
|
4
4
|
"description": "Production-grade AI governance kernel for autonomous agents with fail-closed security and cryptographic audit trails",
|
|
5
5
|
"main": "atlas.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"atlas": "bin/atlas"
|
|
8
8
|
},
|
|
9
9
|
"exports": {
|
|
10
|
-
".": "./
|
|
10
|
+
".": "./index.js",
|
|
11
|
+
"./cli": "./atlas.js"
|
|
11
12
|
},
|
|
12
13
|
"files": [
|
|
14
|
+
"index.js",
|
|
13
15
|
"bin/",
|
|
14
16
|
"atlas.js",
|
|
15
17
|
"src/",
|
|
16
18
|
"config/tier-policies.json",
|
|
19
|
+
"config/trust-boundaries.json",
|
|
20
|
+
"config/sentinel-keys.json",
|
|
17
21
|
"LICENSE",
|
|
18
22
|
"README.md",
|
|
19
23
|
"DISCLAIMER.md",
|
|
@@ -100,4 +104,4 @@
|
|
|
100
104
|
"tar": "^7.5.4",
|
|
101
105
|
"diff": "^8.0.3"
|
|
102
106
|
}
|
|
103
|
-
}
|
|
107
|
+
}
|
package/src/bridge/RingBridge.js
CHANGED
|
@@ -68,8 +68,6 @@ class RingBridge {
|
|
|
68
68
|
console.log(`[RingBridge] MCP Roles: ${Object.keys(mcpConfig.roles || {}).join(', ')}`);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
console.log(`[RingBridge] OPENROUTER_API_KEY present in parent: ${!!process.env.OPENROUTER_API_KEY}`);
|
|
72
|
-
|
|
73
71
|
// ISOLATION: Do not inherit TTY handles (prevents HANDLE_LEAK)
|
|
74
72
|
this.agentProcess = fork(agentPath, [], {
|
|
75
73
|
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
|
|
@@ -5,6 +5,76 @@
|
|
|
5
5
|
* SECURITY CRITICAL: This module must never leak sensitive information.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
|
|
11
|
+
// Hash-chained audit log for SECRET_REDACTION events
|
|
12
|
+
let HashChainedLog = null;
|
|
13
|
+
let _secretEventLog = null;
|
|
14
|
+
const SECRET_EVENT_LOG_PATH = path.join(process.cwd(), '.atlas', 'audit', 'secret_events.chainlog');
|
|
15
|
+
|
|
16
|
+
function getSecretEventLog() {
|
|
17
|
+
if (!HashChainedLog) {
|
|
18
|
+
try {
|
|
19
|
+
HashChainedLog = require('../kernel/io/HashChainedLog').HashChainedLog;
|
|
20
|
+
} catch (e) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (!_secretEventLog) {
|
|
25
|
+
try {
|
|
26
|
+
const dir = path.dirname(SECRET_EVENT_LOG_PATH);
|
|
27
|
+
if (!fs.existsSync(dir)) {
|
|
28
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
_secretEventLog = new HashChainedLog(SECRET_EVENT_LOG_PATH, {
|
|
31
|
+
name: 'SecretEventLog',
|
|
32
|
+
panicOnFailure: false
|
|
33
|
+
});
|
|
34
|
+
_secretEventLog.initialize();
|
|
35
|
+
} catch (e) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return _secretEventLog;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Emit SECRET_REDACTION event to hash-chained audit log
|
|
44
|
+
* @param {string} secretType - Type of secret redacted (API_KEY, TOKEN, etc.)
|
|
45
|
+
* @param {number} count - Number of occurrences redacted
|
|
46
|
+
*/
|
|
47
|
+
function emitSecretRedaction(secretType, count = 1) {
|
|
48
|
+
const log = getSecretEventLog();
|
|
49
|
+
if (log) {
|
|
50
|
+
try {
|
|
51
|
+
const entry = log.append({
|
|
52
|
+
event: 'SECRET_REDACTION',
|
|
53
|
+
timestamp: new Date().toISOString(),
|
|
54
|
+
secret_type: secretType,
|
|
55
|
+
occurrences: count,
|
|
56
|
+
tier: process.env.SENTINEL_TIER || 'DEV',
|
|
57
|
+
// NOTE: Do NOT include the actual secret or any identifying information
|
|
58
|
+
action: 'REDACTED'
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// PROD HARDENING: Anchor to main audit chain
|
|
62
|
+
// Use lazy require to avoid circular dependency (SentinelInterface -> SecretRedactor)
|
|
63
|
+
try {
|
|
64
|
+
const SentinelInterface = require('../kernel/constitution/SentinelInterface');
|
|
65
|
+
const Sentinel = SentinelInterface.SentinelInterface || SentinelInterface;
|
|
66
|
+
if (Sentinel.getInstance) {
|
|
67
|
+
Sentinel.getInstance().logAnchor('SecretEventLog', entry.hash, entry.seq);
|
|
68
|
+
}
|
|
69
|
+
} catch (anchorErr) {
|
|
70
|
+
// Non-fatal, especially likely during early boot if Sentinel not ready
|
|
71
|
+
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
// Silent failure - redaction is more important than logging
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
8
78
|
class SecretRedactor {
|
|
9
79
|
/**
|
|
10
80
|
* Patterns that match sensitive data
|
|
@@ -61,10 +131,20 @@ class SecretRedactor {
|
|
|
61
131
|
}
|
|
62
132
|
|
|
63
133
|
let redacted = text;
|
|
134
|
+
let redactionOccurred = false;
|
|
135
|
+
|
|
64
136
|
for (const { pattern, replacement } of this.PATTERNS) {
|
|
65
137
|
// Create a new RegExp to reset lastIndex
|
|
66
138
|
const regex = new RegExp(pattern.source, pattern.flags);
|
|
67
|
-
|
|
139
|
+
const matches = text.match(regex);
|
|
140
|
+
if (matches && matches.length > 0) {
|
|
141
|
+
redacted = redacted.replace(regex, replacement);
|
|
142
|
+
redactionOccurred = true;
|
|
143
|
+
|
|
144
|
+
// Emit SECRET_REDACTION event (without the actual secret)
|
|
145
|
+
const secretType = replacement.replace(/[\[\]]/g, '').replace('_REDACTED', '');
|
|
146
|
+
emitSecretRedaction(secretType, matches.length);
|
|
147
|
+
}
|
|
68
148
|
}
|
|
69
149
|
|
|
70
150
|
return redacted;
|