mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 16:45:22 +00:00
89 lines
5.2 KiB
Markdown
89 lines
5.2 KiB
Markdown
---
|
|
issue: 73
|
|
issue_title: "node -e command triggers permission prompt despite \"*\": \"allow\" global fallback"
|
|
---
|
|
|
|
# Wildcard matcher fails on multiline bash commands
|
|
|
|
## Problem Statement
|
|
|
|
When a bash command contains newlines (e.g., `node -e "\nimport(...)\n"`), the wildcard matcher's compiled regex `/^.*$/` fails because `.` does not match `\n` by default in JavaScript.
|
|
This causes `evaluate()` to find no matching rule — not even the universal `{ surface: "*", pattern: "*" }` catch-all — and fall through to the hard-coded `"ask"` default, producing a spurious permission prompt.
|
|
|
|
## Goals
|
|
|
|
- Make `wildcardMatch` (and all callers via `compileWildcardPattern`) correctly match values containing newline characters.
|
|
- Zero behavior change for single-line values — this is a strict bug fix.
|
|
|
|
## Non-Goals
|
|
|
|
- Changing the permission evaluation model or rule precedence.
|
|
- Addressing shell-quote tokenization (covered by #72, already landed).
|
|
- Adding multiline-aware pattern syntax (e.g., `**` for newlines) — the existing `*` should simply match everything including newlines.
|
|
|
|
## Background
|
|
|
|
- **Permission surface**: `bash` (but the fix is in the generic wildcard module, affecting all surfaces).
|
|
- **Module**: `src/wildcard-matcher.ts` — `compileWildcardPattern()` builds a `RegExp` by escaping literal segments and joining with `.*`.
|
|
The regex uses no flags, so `.` does not match `\n`.
|
|
- **Call path**: `evaluate()` in `src/rule.ts` calls `wildcardMatch(rule.pattern, value)` for both `surface` and `pattern` fields.
|
|
A multiline bash command is the `value` argument to the pattern match.
|
|
|
|
## Design Overview
|
|
|
|
Add the `s` (dotAll) flag to the regex constructed in `compileWildcardPattern`.
|
|
With `dotAll`, `.` matches any character including line terminators (`\n`, `\r`, `\u2028`, `\u2029`).
|
|
|
|
```typescript
|
|
return {
|
|
pattern,
|
|
state,
|
|
regex: new RegExp(`^${escaped}$`, "s"),
|
|
};
|
|
```
|
|
|
|
This is the minimal, correct fix.
|
|
No new types, no data-shape changes, no config changes.
|
|
|
|
## Module-Level Changes
|
|
|
|
| File | Change |
|
|
| ---------------------------------- | --------------------------------------------------------------------------------- |
|
|
| `src/wildcard-matcher.ts` | Add `"s"` flag to `new RegExp(...)` in `compileWildcardPattern()`. |
|
|
| `tests/wildcard-matcher.test.ts` | Add test cases for multiline values matching `*` and literal-prefix-`*` patterns. |
|
|
| `tests/permission-manager.test.ts` | Add integration test: multiline bash command with `"*": "allow"` returns allow. |
|
|
|
|
## TDD Order
|
|
|
|
1. **test: multiline value fails to match wildcard `*` pattern (red)**
|
|
Add tests in `tests/wildcard-matcher.test.ts`:
|
|
- `wildcardMatch("*", "line1\nline2")` → expected `true`
|
|
- `wildcardMatch("node *", "node -e \"\nfoo\n\"")` → expected `true`
|
|
- `compileWildcardPattern("*", "allow").regex.test("a\nb")` → expected `true`
|
|
|
|
Commit: `test: cover multiline values in wildcardMatch`
|
|
|
|
2. **feat: add dotAll flag to wildcard regex** In `src/wildcard-matcher.ts`, change `new RegExp(...)` to include `"s"` flag.
|
|
Tests from step 1 go green.
|
|
|
|
Commit: `fix: add dotAll flag so wildcard`*`matches newlines (#73)`
|
|
|
|
3. **test: integration — multiline bash command resolves to allow**
|
|
Add a test in `tests/permission-manager.test.ts`:
|
|
- Config: `{ "*": "allow", bash: { "rm -rf *": "deny" } }`
|
|
- `checkPermission("bash", { command: "node -e \"\nimport(...)\n\"" })` → `state: "allow"`
|
|
|
|
Commit: `test: multiline bash command resolves allow via universal fallback`
|
|
|
|
## Risks and Mitigations
|
|
|
|
| Risk | Mitigation |
|
|
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| Could this silently weaken a permission? | No. The `s` flag only makes `*` match what users already expect it to match. A pattern like `rm -rf *` still only matches strings starting with `rm -rf` — it does not gain the ability to match unrelated multiline strings because the literal prefix anchors it. |
|
|
| Over-broad match for patterns containing literal newlines | No user would put literal `\n` in a pattern string in JSON config. The patterns are single-line strings; only values (commands) can be multiline. |
|
|
| Breaks existing tests | Existing tests use single-line values. Adding `s` has no effect on strings without newlines. |
|
|
|
|
## Open Questions
|
|
|
|
None — the fix is unambiguous.
|