Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/ISSUE_TEMPLATE/security_vulnerability.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,29 @@ labels: security
Only use this template for low-severity or already-patched security concerns.

## Vulnerability Type

<!-- e.g., command injection, path traversal, unsafe deserialization -->

## Affected Component

<!-- e.g., core engine, CLI, feed producer, Python TUI -->

## Description

A clear description of the vulnerability and its potential impact.

## Reproduction Steps

1. Configuration or setup required
2. Command or action to trigger
3. Observable result

## Suggested Fix

If you have a recommendation for how to fix this.

## Environment

- hookwise version: (run `hookwise --version`)
- Node.js version:
- OS:
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Thanks for your interest in contributing to hookwise! Here's how to get started.
git clone https://github.com/vishnujayvel/hookwise.git
cd hookwise
npm install
npm test # 1440 tests via vitest
npm test # 1400+ tests via vitest
npm run build # tsup build
npm run typecheck # tsc --noEmit
```
Expand All @@ -25,7 +25,7 @@ src/
cli/ # CLI commands (init, doctor, status, stats, test, migrate)
testing/ # HookRunner, HookResult, GuardTester

tests/ # 1440+ tests
tests/ # 1400+ tests
recipes/ # 12 built-in recipes
examples/ # Example configs
```
Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,4 @@ Key design choices: parameterized SQL everywhere, safe YAML parsing only, no `ev

`git clone`, `npm install`, `npm test` (1,440 tests), `npm run build`. See [CONTRIBUTING.md](CONTRIBUTING.md).

[MIT](LICENSE) -- Built by [Vishnu](https://github.com/vishnujayvel). *Born from the gap between how fast AI makes you feel — and how fast you actually are.*
</content>
</invoke>
[MIT](LICENSE) -- Built by [Vishnu](https://github.com/vishnujayvel). *Born from the gap between how fast AI makes you feel — and how fast you actually are.*
5 changes: 3 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

If you discover a security vulnerability, please report it responsibly:

1. **Do not** open a public issue
2. Email **vishnu@hookwise.dev** with a description, reproduction steps, and impact assessment
1. **For sensitive vulnerabilities**, email **vishnu@hookwise.dev** with a description, reproduction steps, and impact assessment. Do not open a public issue for exploitable or unpatched vulnerabilities.
2. **For low-severity or already-patched issues**, you may use the [Security Vulnerability issue template](https://github.com/vishnujayvel/hookwise/issues/new?template=security_vulnerability.md).
3. You will receive an acknowledgment within 48 hours
4. We aim to release a fix within 7 days for confirmed vulnerabilities

Expand Down Expand Up @@ -51,6 +51,7 @@ The codebase enforces the following security practices by design:
- **No `eval()` or `Function()`** -- Explicitly avoided throughout the codebase and documented in source comments.
- **`execFileSync` for untrusted paths** -- Used where arguments could contain special characters (e.g., calendar credentials path).
- **`spawnSync` without shell** -- The dispatcher passes handler arguments as array elements, preventing shell injection.
- **Scoped `shell: true` usage** -- The status line renderer and test helper (`HookRunner`) use `shell: true` for trusted, locally-authored commands. The feed registry uses `exec()` for producer scripts defined in the user's own `hookwise.yaml` config (same trust level as a Makefile). These are intentional — external/untrusted input never reaches shell execution.

### File System
- **Restrictive permissions** -- Database files use `0o600`; directories use `0o700` (owner-only).
Expand Down
7 changes: 4 additions & 3 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ Any unhandled exception anywhere in the dispatch pipeline results in `exit 0`. h

## Feed Platform Architecture

> **Diagram source:** feed-platform.excalidraw (in docs/assets/) -- open in [Excalidraw](https://excalidraw.com) for an editable hand-drawn version.
> **Diagram:** Feed platform showing 8 producers polling data sources on staggered intervals, writing to an atomic cache bus, consumed by 21 status line segments.
> **Source:** feed-platform.excalidraw (in docs/assets/) -- open in [Excalidraw](https://excalidraw.com) for an editable hand-drawn version.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Update feed-platform counts and source link format to match docs rules.

The diagram description uses counts that conflict with the documented architecture baseline, and the source reference should be a relative file link (for example, docs/assets/feed-platform.excalidraw) rather than plain text.

As per coding guidelines, "Architecture descriptions match current code (v1.2, feed platform, 19 segments, 5 producers)" and "Links to source files must use relative paths and point to files that exist."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/architecture.md` around lines 35 - 36, Update the diagram description
text to match the architecture baseline by changing the producer and segment
counts used in the line describing the feed platform (replace "8 producers" and
"21 status line segments" with "5 producers" and "19 segments") and change the
source reference to a relative file link pointing to the actual asset (use
"docs/assets/feed-platform.excalidraw" as the source link); locate and edit the
feed-platform diagram description string and the source reference text
(feed-platform.excalidraw) in the document to apply these exact replacements.


```mermaid
graph LR
Expand Down Expand Up @@ -95,9 +96,9 @@ src/
tui/ # Interactive TUI (Python Textual)
hookwise_tui/ # App, tabs, widgets, data readers

tests/ # 1440+ tests across 61 test files
tests/ # 1400+ tests across 61 test files
core/ # Unit tests for each module
integration/ # End-to-end dispatch flow tests
integration/ # Mock-based integration tests (dispatch flow, pipeline wiring)
performance/ # Benchmarks and import boundary tests
cli/ # CLI command tests

Expand Down
8 changes: 4 additions & 4 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ hookwise migrate Migrate from Python hookwise (v0.1.0) to TypeScript
| Preset | What you get |
|--------|-------------|
| `minimal` | Guards only -- just the safety rails |
| `coaching` | Guards + metacognition + builder's trap + status line |
| `coaching` | Guards + metacognition + builder's trap + communication |
| `analytics` | Guards + SQLite session tracking |
| `full` | Everything enabled |

Expand All @@ -57,14 +57,14 @@ hookwise includes testing utilities so you can validate guards in CI:
```typescript
import { GuardTester } from "hookwise/testing";

const tester = new GuardTester("hookwise.yaml");
const tester = new GuardTester({ configPath: "hookwise.yaml" });

// Test blocking
const blocked = tester.evaluate("Bash", { command: "rm -rf /" });
const blocked = tester.testToolCall("Bash", { command: "rm -rf /" });
expect(blocked.action).toBe("block");

// Test allowing
const allowed = tester.evaluate("Bash", { command: "ls -la" });
const allowed = tester.testToolCall("Bash", { command: "ls -la" });
expect(allowed.action).toBe("allow");
```

Expand Down
5 changes: 5 additions & 0 deletions scripts/calendar-feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ def main():
# full calendar scope (e.g., shared with Google Calendar MCP).
# Both calendar and calendar.readonly work for read-only queries.
creds = Credentials.from_authorized_user_file(TOKEN_PATH)
# Verify loaded scopes are compatible (must include calendar or calendar.readonly)
if creds and creds.scopes and not any(
s.endswith("calendar") or s.endswith("calendar.readonly") for s in creds.scopes
):
creds = None # Incompatible scopes — re-trigger OAuth
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/init.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function runInit(preset: string, dir: string): Step[] {
try {
let yamlContent: string;
if (effectivePreset === "minimal") {
yamlContent = `# hookwise configuration\n# Preset: minimal\n# Docs: https://github.com/vishnujayvel/hookwise\n\nversion: 1\nguards: []\n`;
yamlContent = `# hookwise configuration\n# Preset: minimal\n# Docs: https://github.com/vishnujayvel/hookwise\n\nversion: 1\nguards: []\ntui:\n auto_launch: true\n`;
} else {
const config = applyPreset(getDefaultConfig(), effectivePreset);
const snakeCased = deepCamelToSnake(config);
Expand Down
3 changes: 2 additions & 1 deletion src/core/tui-launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,10 @@ export function launchTui(config: TuiConfig, pidPath?: string): boolean {
// Note: osascript is transient — its PID is not the python3 PID, so we
// skip PID-based duplicate prevention for newWindow mode.
const pythonCmd = resolveTuiPython();
const escapedCmd = pythonCmd.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
const child = spawn(
"osascript",
["-e", `tell application "Terminal" to do script "${pythonCmd} -m hookwise_tui"`],
["-e", `tell application "Terminal" to do script "${escapedCmd} -m hookwise_tui"`],
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
{
detached: true,
stdio: "ignore",
Expand Down
4 changes: 2 additions & 2 deletions tests/core/tui-launcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ describe("launchTui", () => {

expect(mockedSpawn).toHaveBeenCalledWith(
"osascript",
["-e", 'tell application "Terminal" to do script "python3 -m hookwise_tui"'],
["-e", expect.stringContaining("-m hookwise_tui")],
expect.objectContaining({ detached: true, stdio: "ignore" }),
);
});
Expand Down Expand Up @@ -213,7 +213,7 @@ describe("launchTui", () => {
launchTui(config, pidPath);

expect(mockedSpawn).toHaveBeenCalledWith(
"python3",
expect.stringContaining("python3"),
["-m", "hookwise_tui"],
expect.objectContaining({ detached: true, stdio: "ignore" }),
);
Expand Down