|
| 1 | +# Copilot Instructions for FixSprayExploit Plugin |
| 2 | + |
| 3 | +## Repository Overview |
| 4 | + |
| 5 | +This repository contains a SourcePawn plugin for SourceMod that detects and prevents spray exploits in Source engine games. The plugin protects game servers from malicious spray files that can crash clients by validating spray file headers and blocking invalid uploads. |
| 6 | + |
| 7 | +**Key Functionality:** |
| 8 | +- Real-time spray file validation during upload and usage |
| 9 | +- Automatic blocking and cleanup of malicious spray files |
| 10 | +- Player punishment (kick/ban) for exploit attempts |
| 11 | +- Integration with SourceBans++ and MaterialAdmin for banning |
| 12 | +- Comprehensive logging of spray activity |
| 13 | +- Support for multiple Source engine games (TF2, CSS, L4D2, etc.) |
| 14 | + |
| 15 | +## Project Structure |
| 16 | + |
| 17 | +``` |
| 18 | +addons/sourcemod/ |
| 19 | +├── scripting/ |
| 20 | +│ ├── FixSprayExploit.sp # Main plugin implementation (~1150 lines) |
| 21 | +│ └── include/ |
| 22 | +│ └── spray_exploit.inc # Native functions and forwards |
| 23 | +sourceknight.yaml # Build configuration |
| 24 | +.github/workflows/ci.yml # CI/CD pipeline |
| 25 | +``` |
| 26 | + |
| 27 | +## Technical Environment |
| 28 | + |
| 29 | +**Language & Platform:** |
| 30 | +- **Language**: SourcePawn (SourceMod scripting language) |
| 31 | +- **Platform**: SourceMod 1.11.0+ (configured for 1.11.0-git6917) |
| 32 | +- **Build Tool**: SourceKnight 0.1 |
| 33 | +- **Engine Support**: All Source engine games (TF2, CSS, L4D2, HL2DM, ZPS, etc.) |
| 34 | + |
| 35 | +**Dependencies:** |
| 36 | +- SourceMod 1.11.0-git6917 (auto-downloaded via SourceKnight) |
| 37 | +- SourceBans++ (optional, for enhanced banning) |
| 38 | +- MaterialAdmin (optional, for alternative banning) |
| 39 | + |
| 40 | +## Build System |
| 41 | + |
| 42 | +The project uses **SourceKnight**, a modern SourceMod build tool: |
| 43 | + |
| 44 | +### Build Configuration (`sourceknight.yaml`) |
| 45 | +- **Output**: `/addons/sourcemod/plugins` (compiled `.smx` files) |
| 46 | +- **Target**: `FixSprayExploit` (builds `FixSprayExploit.smx`) |
| 47 | +- **Dependencies**: Auto-downloaded and unpacked during build |
| 48 | + |
| 49 | +### Building Locally |
| 50 | +```bash |
| 51 | +# Install SourceKnight if not available |
| 52 | +# Build the plugin |
| 53 | +sourceknight build |
| 54 | + |
| 55 | +# Output will be in .sourceknight/package/addons/sourcemod/plugins/ |
| 56 | +``` |
| 57 | + |
| 58 | +**Note**: SourceKnight may not be available in all environments. The GitHub Actions CI/CD pipeline is the primary build method. For local development, you can use the traditional SourceMod compiler (`spcomp`) if needed. |
| 59 | + |
| 60 | +### CI/CD Pipeline |
| 61 | +- Uses GitHub Actions with `maxime1907/action-sourceknight@v1` |
| 62 | +- Builds on Ubuntu 24.04 |
| 63 | +- Creates release packages automatically |
| 64 | +- Tags `latest` release from main/master branch |
| 65 | + |
| 66 | +## Code Architecture |
| 67 | + |
| 68 | +### Main Plugin (`FixSprayExploit.sp`) |
| 69 | + |
| 70 | +**Core Components:** |
| 71 | +1. **File Validation Engine** (lines 995-1105): Validates spray file headers against known exploit patterns |
| 72 | +2. **Player Spray Monitoring** (lines 744-827): Hooks `Player Decal` temp entities to intercept spray attempts |
| 73 | +3. **File Receive/Send Hooks** (lines 914-992): Monitors file transfers to/from clients |
| 74 | +4. **Punishment System** (lines 887-912): Handles kicking/banning of exploit users |
| 75 | +5. **Cleanup System** (lines 582-680): Moves invalid sprays to backup folder |
| 76 | + |
| 77 | +**Key Data Structures:** |
| 78 | +- `g_smChecked`: StringMap cache of validated files |
| 79 | +- `g_smReceive`: StringMap tracking received files |
| 80 | +- `g_smWaiting`: StringMap preventing duplicate log spam |
| 81 | +- `g_iVal[]`: Expected byte pattern for valid spray headers |
| 82 | + |
| 83 | +### Include File (`spray_exploit.inc`) |
| 84 | + |
| 85 | +**Provides:** |
| 86 | +- `OnSprayExploit(client, index, value)` forward for third-party plugins |
| 87 | +- `SprayExploitFixer_LogCustom()` native for custom logging |
| 88 | + |
| 89 | +## SourcePawn Coding Guidelines |
| 90 | + |
| 91 | +### Style Requirements |
| 92 | +- Use `#pragma semicolon 1` and `#pragma newdecls required` |
| 93 | +- Indentation: 4 spaces (represented as tabs) |
| 94 | +- Variables: camelCase for locals, PascalCase for functions, prefix globals with `g_` |
| 95 | +- No unnecessary headers/comments (plugin has extensive changelog - avoid this pattern) |
| 96 | +- Delete trailing spaces |
| 97 | + |
| 98 | +### Best Practices Applied |
| 99 | +✅ **Memory Management**: Uses `delete` for StringMaps/ArrayLists instead of `.Clear()` |
| 100 | +✅ **Async Operations**: File operations use timers to prevent timeouts |
| 101 | +✅ **StringMaps over Arrays**: Efficient data storage |
| 102 | +✅ **Error Handling**: Comprehensive validation and logging |
| 103 | +✅ **Performance**: Caching validated files, batched processing |
| 104 | + |
| 105 | +### Anti-Patterns to Avoid |
| 106 | +❌ Extensive changelog headers (existing code has this but avoid in new code) |
| 107 | +❌ Using `.Clear()` on StringMaps (causes memory leaks) |
| 108 | +❌ Synchronous file operations in loops |
| 109 | +❌ Hardcoded values without configuration |
| 110 | + |
| 111 | +## Development Workflows |
| 112 | + |
| 113 | +### Adding New Exploit Detection |
| 114 | +1. Update `g_iVal[]` array with new byte patterns |
| 115 | +2. Modify `ValFile()` function for new validation logic |
| 116 | +3. Add corresponding test cases to `RecursiveSearchDirs()` |
| 117 | +4. Update `g_hCvarPunish` handling if needed |
| 118 | + |
| 119 | +### Integrating New Banning Systems |
| 120 | +1. Add optional include: `#tryinclude <newsystem>` |
| 121 | +2. Add library detection in `OnLibraryAdded()/OnLibraryRemoved()` |
| 122 | +3. Extend `TestClient()` function with new banning method |
| 123 | +4. Mark natives as optional in `AskPluginLoad2()` |
| 124 | + |
| 125 | +### Performance Optimization |
| 126 | +- Monitor `MAX_READ` constant (current: 50 files per batch) |
| 127 | +- Use `TIMEOUT_LOG` to prevent log spam (current: 10.0 seconds) |
| 128 | +- Cache results in StringMaps to avoid repeated validation |
| 129 | +- Use `RequestFrame()` for async operations |
| 130 | + |
| 131 | +## Testing & Validation |
| 132 | + |
| 133 | +### Manual Testing |
| 134 | +```bash |
| 135 | +# Test spray file validation |
| 136 | +sm_spray_test |
| 137 | + |
| 138 | +# Monitor real-time activity |
| 139 | +sm_cvar spray_exploit_fixer_log 1 |
| 140 | +sm_cvar spray_exploit_fixer_msg 1 |
| 141 | +``` |
| 142 | + |
| 143 | +### Integration Testing |
| 144 | +- Test with SourceBans++ integration (`g_bSourceBans`) |
| 145 | +- Test with MaterialAdmin integration (`g_bMaterialAdmin`) |
| 146 | +- Validate different engine support (TF2 has special handling) |
| 147 | +- Test file cleanup and backup functionality |
| 148 | + |
| 149 | +### Configuration Testing |
| 150 | +```bash |
| 151 | +# Test punishment modes |
| 152 | +sm_cvar spray_exploit_fixer_punish 1 # PlayerDecal only |
| 153 | +sm_cvar spray_exploit_fixer_punish 2 # FileCheck only |
| 154 | +sm_cvar spray_exploit_fixer_punish 3 # Both |
| 155 | + |
| 156 | +# Test banning (not available in TF2) |
| 157 | +sm_cvar spray_exploit_fixer_ban 1 |
| 158 | +sm_cvar spray_exploit_fixer_kick 1 |
| 159 | +sm_cvar spray_exploit_fixer_bantime 5 |
| 160 | +``` |
| 161 | + |
| 162 | +## Security Considerations |
| 163 | + |
| 164 | +### Exploit Detection Logic |
| 165 | +- **Header Validation**: Checks VTF file header against `g_iVal[]` patterns |
| 166 | +- **RIFF/WAVE Detection**: Special handling for audio files (lines 1053-1058) |
| 167 | +- **Size Validation**: Prevents oversized dimensions (lines 1079-1086) |
| 168 | +- **Flag Validation**: Blocks dangerous VTF flags (line 1086) |
| 169 | + |
| 170 | +### File System Security |
| 171 | +- Moves invalid files to `backup_sprays/` folder instead of deletion |
| 172 | +- Validates file paths to prevent directory traversal |
| 173 | +- Handles both `.dat` and `.dat.ztmp` file extensions |
| 174 | +- Recursive cleanup of empty directories |
| 175 | + |
| 176 | +## File Exclusions (.gitignore) |
| 177 | + |
| 178 | +The following should be excluded from version control: |
| 179 | +- `build/`, `release/` - Build artifacts |
| 180 | +- `*.smx` - Compiled plugins |
| 181 | +- `plugins/` - Plugin binaries |
| 182 | +- `.sourceknight/` - SourceKnight build cache |
| 183 | +- `.venv/` - Python virtual environments |
| 184 | + |
| 185 | +## Common Tasks |
| 186 | + |
| 187 | +### Adding ConVar |
| 188 | +```sourcepawn |
| 189 | +ConVar g_hCvarNewSetting = CreateConVar("spray_exploit_fixer_newsetting", "0", "Description"); |
| 190 | +AutoExecConfig(true, "spray_exploit_fixer"); |
| 191 | +``` |
| 192 | + |
| 193 | +### Adding New Log Message |
| 194 | +```sourcepawn |
| 195 | +if( g_hCvarLog.IntValue ) LogCustom("New event: %s from %N", data, client); |
| 196 | +if( g_hCvarMsg.IntValue ) PrintToServer("[Spray Exploit] New event: %s", data); |
| 197 | +``` |
| 198 | + |
| 199 | +### Extending File Validation |
| 200 | +```sourcepawn |
| 201 | +// In ValFile() function, add new checks: |
| 202 | +if( condition_check ) { |
| 203 | + return i; // Return position of invalid byte |
| 204 | +} |
| 205 | +``` |
| 206 | + |
| 207 | +## Debugging & Troubleshooting |
| 208 | + |
| 209 | +### Common Issues |
| 210 | +1. **Build Failures**: Check SourceKnight version compatibility |
| 211 | +2. **File Not Found**: Verify `spray_exploit_fixer_path` cvar is correct |
| 212 | +3. **Memory Leaks**: Ensure StringMaps are `delete`d, not `.Clear()`ed |
| 213 | +4. **Timeouts**: Increase batch size or timer delays for large file sets |
| 214 | + |
| 215 | +### Debug Logging |
| 216 | +- Set `spray_exploit_fixer_log 1` for all activity |
| 217 | +- Set `spray_exploit_fixer_msg 1` for console output |
| 218 | +- Check `sourcemod/logs/spray_downloads.log` for detailed logs |
| 219 | + |
| 220 | +### Performance Monitoring |
| 221 | +- Monitor `g_iTotal` counter in batch processing |
| 222 | +- Check `g_fTime` for operation duration in `CmdSprays` |
| 223 | +- Watch for script execution timeouts during file operations |
| 224 | + |
| 225 | +This plugin demonstrates advanced SourcePawn techniques for file validation, async processing, and multi-platform compatibility. Focus on maintaining the security-first approach while ensuring server performance. |
| 226 | + |
| 227 | +## Quick Reference |
| 228 | + |
| 229 | +### Key Files |
| 230 | +- `addons/sourcemod/scripting/FixSprayExploit.sp` - Main plugin (1150 lines) |
| 231 | +- `addons/sourcemod/scripting/include/spray_exploit.inc` - API definitions |
| 232 | +- `sourceknight.yaml` - Build configuration |
| 233 | +- `.github/workflows/ci.yml` - CI/CD pipeline |
| 234 | + |
| 235 | +### Important Constants |
| 236 | +- `MAX_READ = 50` - Files processed per batch |
| 237 | +- `TIMEOUT_LOG = 10.0` - Seconds between duplicate log entries |
| 238 | +- `PATH_BACKUP = "backup_sprays"` - Invalid spray storage folder |
| 239 | + |
| 240 | +### Key CVars |
| 241 | +- `spray_exploit_fixer_punish` - Which exploits to test (0-3) |
| 242 | +- `spray_exploit_fixer_ban` - Ban malicious users (0-1) |
| 243 | +- `spray_exploit_fixer_log` - Logging level (0-2) |
| 244 | +- `spray_exploit_fixer_msg` - Console output level (0-2) |
0 commit comments