2 Commits

Author SHA1 Message Date
shoko
27c8cb3597 Add security audit to polymarket-browse review
CRITICAL: Telegram bot token exposed in process command line
HIGH: HTML injection in Telegram messages
MEDIUM: Insufficient --search URL encoding
MEDIUM: No bounds check on --detail
MEDIUM: Potential DoS via large API response
LOW: Bare except: clauses
LOW: No API rate limiting

Includes fix recommendations and immediate actions for users.
2026-03-25 09:27:28 +00:00
shoko
4a33d6924e Add polymarket-browse skill review (2026-03-25)
- Deep analysis of SKILL.md and browse.py
- Line length analysis (worst: 209 chars at print_browse signature)
- Duplicate code patterns (3 time functions, 2 tradeable checkers)
- Bug findings (bare except:, unused variables, 11-param function)
- Recommendations for refactoring and unit testing
- Proposed test structure under tests/
- Summary table categorized by priority/effort
2026-03-25 09:12:05 +00:00
7 changed files with 383 additions and 3162 deletions

1
.gitignore vendored
View File

@@ -2,4 +2,3 @@ __pycache__/
*.pyc
*.pyo
.DS_Store
.worktrees/

View File

@@ -1,25 +0,0 @@
# Security Policy
## Security Audit (2026-03-25)
This document tracks security issues found during the 2026-03-25 audit.
## Fixed Issues
| Issue | Severity | Fixed Date | Fix |
|-------|----------|------------|-----|
| Telegram bot token in process command line | CRITICAL | 2026-03-25 | Switched to Python urlopen from curl subprocess |
| HTML injection in Telegram messages | HIGH | 2026-03-25 | Added escape_html() function |
| Insufficient --search URL encoding | MEDIUM | 2026-03-26 | Use urllib.parse.quote() |
| --detail bounds not validated | MEDIUM | 2026-03-26 | Error on out of range |
| No response size limits | MEDIUM | 2026-03-26 | MAX_RESPONSE_SIZE check |
| Bare except: clauses | LOW | 2026-03-26 | Catch specific exceptions |
| No API rate limiting | LOW | 2026-03-26 | TokenBucket rate limiter |
## Open Issues
All security issues from this audit have been addressed in subsequent releases.
## Reporting Security Issues
If you find a security vulnerability, please report it by opening an issue.

View File

@@ -1,6 +1,5 @@
---
name: polymarket-browse
version: 0.0.3
category: research
description: Browse tradeable Polymarket events by game category. Shows active matches with ML odds (cents format), volume, tournament, and market URLs. Supports Counter Strike, League of Legends, Dota 2, Valorant, NBA, NFL, UFC, Tennis.
---
@@ -35,7 +34,7 @@ hermes mcp add polymarket https://docs.polymarket.com/mcp
## Usage
```
polymarket-browse [--category "Counter Strike"] [--limit 5] [--matches N] [--non-matches N] [--search "TeamName"] [--matches-only] [--non-matches-only] [--detail N] [--raw] [--telegram] [--no-cache] [--max-total N] [--starts-before TIMESTAMP] [--timezone UTC+X]
polymarket-browse [--category "Counter Strike"] [--limit 5] [--matches N] [--non-matches N] [--search "TeamName"] [--matches-only] [--non-matches-only] [--detail N] [--raw] [--telegram]
```
## Arguments
@@ -47,17 +46,9 @@ polymarket-browse [--category "Counter Strike"] [--limit 5] [--matches N] [--non
- `--search` : Free-text team/term search within the selected category. Appends to the category query. Example: `--category "Counter Strike" --search "FlyQuest"`
- `--matches-only` : Show only match markets (suppress non-match section).
- `--non-matches-only` : Show only non-match markets (suppress match section).
- `--detail N` : Show detailed markets for match event N (1-indexed).
- Only applies to MATCH markets (not non-match/tournament markets)
- Default: 1 (auto-shows details for first match)
- Set to 0 to disable detail view
- If N exceeds available matches, shows error with available range
- `--detail` : Index of match event (1-indexed) to show detailed markets. Default: 1. Set to 0 to disable.
- `--list-categories` : List available game categories and exit
- `--raw` : Show all events without tradeable filter (for debugging). Includes fetch stats.
- `--no-cache` : Disable caching and fetch fresh data from the API.
- `--max-total` : Maximum total events to fetch before early exit. Default: no limit. Useful for quick snapshots.
- `--starts-before` : Unix timestamp filter. Only show match events starting before this time (LIVE events always shown regardless of timestamp).
- `--timezone` : Timezone for displaying times. Format: `UTC+X` or `UTC-X` (e.g., `UTC+7`, `UTC-5`). Default: UTC+7 (WIB).
- `--telegram` : Send results to Telegram. Requires `BOT_TOKEN` and `CHAT_ID` in environment variables.
## Output Format
@@ -127,158 +118,16 @@ Use `--raw` to disable the tradeable filter and see all match markets regardless
## Pagination
The script fetches **ALL pages** until the API runs out of results.
### Parallel Fetching
Pages are fetched in **parallel batches of 5** using ThreadPoolExecutor. This significantly reduces fetch time:
| Scenario | Without Parallelization | With Parallelization |
|----------|------------------------|---------------------|
| 10 pages (50 events) | ~20s (2s per page × 10) | ~4s (2s per batch × 2 batches) |
| 20 pages (100 events) | ~40s | ~8s |
The script first fetches page 1 to determine total pages, then fetches remaining pages in parallel batches of 5.
The script fetches **ALL pages** until the API runs out of results (up to 100 pages as a safety cap).
## Rate Limiting
- TokenBucket rate limiter: 10 API calls per second
- Exponential backoff on retries: 2s → 4s → 8s → 16s → 32s
- Exponential backoff: 2s → 4s → 8s → 16s → 32s
- Max 5 retries before aborting
**URL Encoding**: Special characters in `--search` (e.g., `&`, `=`, `%`, `+`, `#`) are properly encoded to prevent URL injection.
## Caching
Results are cached in `~/.cache/polymarket-browse/` with a **5-minute TTL** to reduce redundant API calls.
- Use `--no-cache` to bypass the cache and fetch fresh data
- Cached data is automatically used when available and not expired
- Useful when running the script repeatedly (e.g., for monitoring)
## Odds Format
All odds are shown in **cents** format:
- `30c` = 0.30 probability
- `95c` = 0.95 probability
- `GamerLegion 28c | 72c Team Yandex` = GamerLegion at 28c, Team Yandex at 72c
## Troubleshooting
### "WARNING: Partial fetch" appears
The API returned incomplete data due to an error/timeout. Results shown may be incomplete. Try again with `--no-cache` to force a fresh fetch.
### No markets appear
- Verify your category is correct: `--list-categories`
- Try with `--raw` to see all events (not just tradeable ones)
- Some categories may have no active match markets at certain times
### Why did my match disappear?
Matches are filtered out when:
- They have ended (startTime > 4 hours ago)
- BO2 matches ended in a tie (1-1)
- The market has converged (bestBid >= 0.99 or bestAsk <= 0.01)
- The event has ended (endDate passed)
### Telegram not working
- Verify `BOT_TOKEN` and `CHAT_ID` environment variables are set
- Ensure bot is started and chat ID is correct
- Check Telegram has not blocked the bot
## Examples
### Basic usage
```bash
# Browse Counter Strike matches (default)
polymarket-browse
# Browse NBA matches
polymarket-browse --category NBA
# Show more results
polymarket-browse --limit 10
```
### Searching for teams
```bash
# Find FlyQuest Counter Strike matches
polymarket-browse --category "Counter Strike" --search "FlyQuest"
# Find any team/event across category
polymarket-browse --category "Counter Strike" --search "Spirit"
```
### Filtering results
```bash
# Show only match markets (no tournament futures)
polymarket-browse --matches-only
# Show only non-match markets (tournaments, props)
polymarket-browse --non-matches-only
# Different limits for each section
polymarket-browse --matches 10 --non-matches 5
```
### Using --detail
```bash
# Show details for 1st match (default behavior, auto-enabled)
polymarket-browse --detail 1
# Show details for 3rd match
polymarket-browse --detail 3
# Disable detail view
polymarket-browse --detail 0
```
### Debugging
```bash
# Show all events without tradeable filter
polymarket-browse --raw
# Force fresh data (bypass cache)
polymarket-browse --no-cache
# Limit total events for quick snapshot
polymarket-browse --max-total 20
```
### Timezone
```bash
# Display times in different timezone (default: UTC+7/WIB)
polymarket-browse --timezone UTC+8
polymarket-browse --timezone UTC-5
```
## Changelog
### v0.0.3 (Current)
- Added `--starts-before` filter for filtering match events by start time
- Added `--timezone` argument for display timezone configuration (default: UTC+7)
- Added TokenBucket rate limiter (10 calls/sec) to prevent API overload
- Added dynamic response size limits to prevent memory exhaustion
- Added proper URL encoding for special characters in --search
- Replaced bare `except:` with specific exception handling
- Improved `--detail` argument validation with error on out-of-range
- Added Troubleshooting, Examples sections to documentation
- Created SECURITY.md for audit tracking
### v0.0.2
- Added `--matches-only` and `--non-matches-only` filters
- Added `--max-total` for limiting fetch size
- Added Telegram support with `--telegram` flag
- Improved BO2 tie detection
### v0.0.1
- Initial release
- Basic Polymarket browsing by category
- Match/non-match market filtering
- Moneyline odds display
## Credits
**Author:** shokollm
**Repository:** https://github.com/shokollm/jujutsu-skills
Built for Hermes Agent and OpenClaw.

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
# Tests package

File diff suppressed because it is too large Load Diff