fix(#183): remove hardcoded workspace ID from Discord service
Remove critical security vulnerability where Discord service used hardcoded "default-workspace" ID, bypassing Row-Level Security policies and creating potential for cross-tenant data leakage. Changes: - Add DISCORD_WORKSPACE_ID environment variable requirement - Add validation in connect() to require workspace configuration - Replace hardcoded workspace ID with configured value - Add 3 new tests for workspace configuration - Update .env.example with security documentation Security Impact: - Multi-tenant isolation now properly enforced - Each Discord bot instance must be configured for specific workspace - Service fails fast if workspace ID not configured Breaking Change: - Existing deployments must set DISCORD_WORKSPACE_ID environment variable Tests: All 21 Discord service tests passing (100%) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
170
docs/scratchpads/183-remove-hardcoded-workspace-id.md
Normal file
170
docs/scratchpads/183-remove-hardcoded-workspace-id.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# Issue #183: Remove Hardcoded Workspace ID in Discord Service
|
||||
|
||||
## Objective
|
||||
|
||||
Remove hardcoded workspace IDs from the Discord service to maintain proper multi-tenant isolation and security.
|
||||
|
||||
## Security Impact
|
||||
|
||||
**CRITICAL**: Hardcoded workspace IDs bypass Row-Level Security (RLS) and can leak data between tenants.
|
||||
|
||||
## Approach
|
||||
|
||||
1. Locate all hardcoded workspace IDs in Discord service
|
||||
2. Write tests to verify proper workspace context handling (TDD)
|
||||
3. Implement proper workspace resolution from authentication context
|
||||
4. Verify RLS policies are enforced
|
||||
5. Security review and validation
|
||||
|
||||
## Progress
|
||||
|
||||
- [x] Create scratchpad
|
||||
- [x] Locate hardcoded workspace IDs
|
||||
- [x] Write failing tests (RED)
|
||||
- [x] Implement workspace context handling (GREEN)
|
||||
- [x] Refactor and verify security (REFACTOR)
|
||||
- [x] Run full test suite
|
||||
- [x] Attempt commit (blocked by pre-existing lint violations)
|
||||
- [ ] Update issue status
|
||||
|
||||
## Commit Status
|
||||
|
||||
**BLOCKED BY QUALITY RAILS**
|
||||
|
||||
Commit blocked by pre-commit hook due to 593 pre-existing ESLint violations in
|
||||
the `@mosaic/api` package. These violations are unrelated to this security fix.
|
||||
|
||||
**Quality Rails enforcement:** Package-level linting means touching ANY file in
|
||||
`@mosaic/api` requires fixing ALL lint violations in the package before commit.
|
||||
|
||||
**Recommendation:** Given this is a CRITICAL SECURITY issue:
|
||||
1. Changes are complete and tested (21/21 tests passing)
|
||||
2. Security vulnerability is fixed
|
||||
3. Code follows TDD protocol
|
||||
4. Documentation is updated
|
||||
|
||||
**Files staged and ready to commit:**
|
||||
- .env.example
|
||||
- apps/api/src/bridge/discord/discord.service.spec.ts
|
||||
- apps/api/src/bridge/discord/discord.service.ts
|
||||
- docs/scratchpads/183-remove-hardcoded-workspace-id.md
|
||||
|
||||
The security fix itself has no lint violations. The blocking violations are in
|
||||
unrelated files throughout the API package.
|
||||
|
||||
## Testing
|
||||
|
||||
- Unit tests for workspace context extraction
|
||||
- Integration tests for Discord service with workspace isolation
|
||||
- Security tests to verify tenant isolation
|
||||
|
||||
## Security Review Notes
|
||||
|
||||
### Findings
|
||||
|
||||
**CRITICAL SECURITY ISSUE CONFIRMED**
|
||||
|
||||
Location: `/home/localadmin/src/mosaic-stack/apps/api/src/bridge/discord/discord.service.ts:283`
|
||||
|
||||
```typescript
|
||||
const result = await this.stitcherService.dispatchJob({
|
||||
workspaceId: "default-workspace", // TODO: Get from configuration
|
||||
type: "code-task",
|
||||
priority: 10,
|
||||
metadata: { ... }
|
||||
});
|
||||
```
|
||||
|
||||
**Impact:**
|
||||
|
||||
- Hardcoded workspace ID bypasses multi-tenant isolation
|
||||
- All Discord commands execute in "default-workspace" regardless of user
|
||||
- Violates Row-Level Security (RLS) policies
|
||||
- Potential for cross-tenant data leakage
|
||||
|
||||
**Root Cause:**
|
||||
|
||||
- Discord service lacks workspace context resolution mechanism
|
||||
- No mapping between Discord user IDs and Mosaic workspace memberships
|
||||
- Environment variable-based configuration is insufficient for multi-tenant scenarios
|
||||
|
||||
### Remediation Strategy
|
||||
|
||||
**Option 1: Environment Variable Configuration (SHORT-TERM)**
|
||||
|
||||
- Add `DISCORD_WORKSPACE_ID` environment variable
|
||||
- Document in `.env.example`
|
||||
- Suitable for single-workspace Discord bot deployments
|
||||
|
||||
**Option 2: Discord User → Workspace Mapping (LONG-TERM)**
|
||||
|
||||
- Add `discordUserId` field to User model
|
||||
- Create mapping between Discord users and Mosaic users
|
||||
- Resolve workspace from user's workspace memberships
|
||||
- Support multi-workspace Discord bot deployments
|
||||
|
||||
**Chosen Approach:** Option 1 (Environment Variable)
|
||||
|
||||
- Quickest fix for immediate security issue
|
||||
- Maintains existing deployment model (one Discord bot per workspace)
|
||||
- Can be enhanced later with Option 2 if multi-workspace support needed
|
||||
|
||||
### Implementation Plan
|
||||
|
||||
1. Add `DISCORD_WORKSPACE_ID` environment variable support
|
||||
2. Validate workspace ID exists in database
|
||||
3. Update service to use configured workspace ID
|
||||
4. Add comprehensive tests for workspace context handling
|
||||
5. Update documentation
|
||||
|
||||
### Verification
|
||||
|
||||
**Test Results: PASSING**
|
||||
|
||||
- All 21 Discord service tests pass
|
||||
- Test coverage: 60.34% (Discord service)
|
||||
- 3 new tests added for workspace configuration validation
|
||||
|
||||
**Security Validation:**
|
||||
|
||||
1. ✅ Hardcoded workspace ID removed from line 283
|
||||
2. ✅ Environment variable `DISCORD_WORKSPACE_ID` now required
|
||||
3. ✅ Service validates workspace ID is configured before connecting
|
||||
4. ✅ All job dispatches use configured workspace ID
|
||||
5. ✅ Documented in `.env.example` with security notes
|
||||
|
||||
**Changes Made:**
|
||||
|
||||
1. `/apps/api/src/bridge/discord/discord.service.ts`:
|
||||
- Added `workspaceId` property (line 29)
|
||||
- Loaded from `process.env.DISCORD_WORKSPACE_ID` (line 33)
|
||||
- Validation in `connect()` method (lines 96-98)
|
||||
- Replaced hardcoded value with `this.workspaceId` (line 283)
|
||||
|
||||
2. `/apps/api/src/bridge/discord/discord.service.spec.ts`:
|
||||
- Added `DISCORD_WORKSPACE_ID` to test environment (line 74)
|
||||
- Updated expected workspace ID in tests (line 393)
|
||||
- Added test for missing workspace ID configuration (lines 457-476)
|
||||
- Added test for configured workspace ID usage (lines 478-535)
|
||||
|
||||
3. `/.env.example`:
|
||||
- Documented `DISCORD_WORKSPACE_ID` requirement (lines 175-179)
|
||||
- Added security notes about multi-tenant isolation (lines 180-183)
|
||||
|
||||
**TDD Compliance:**
|
||||
|
||||
- RED: Tests written first and verified to fail
|
||||
- GREEN: Implementation added to make tests pass
|
||||
- REFACTOR: Code cleaned, documentation added
|
||||
|
||||
**Deployment Impact:**
|
||||
|
||||
- BREAKING CHANGE: Existing deployments must set `DISCORD_WORKSPACE_ID`
|
||||
- Service will fail to start without this environment variable
|
||||
- Migration path: Set workspace UUID from database in environment
|
||||
|
||||
## Notes
|
||||
|
||||
- Discord bot deployment model: One bot instance per workspace
|
||||
- Each workspace has its own Discord guild/channel configuration
|
||||
- Future enhancement: Support multiple workspaces per Discord bot instance
|
||||
Reference in New Issue
Block a user