T09 · Insecure Skill Coding Practices
- Location
post_giveaway_tweet.py:31- Finding
Hard-Coded X/Twitter OAuth Credentials in Executable Posting Script
- Content
View full analysis
tweepy.Client: """Create and return a Tweepy client.""" return tweepy.Client( consumer_key="apwa7XeSfXPcYXcP0lTyweaqe", consumer_secret="syAIe9PpVJL2aQFSiZZDtBcXgxZ1uHijtgKqF0wFzOZF6B6n6W", access_token="1944928465121124352-P9hVuOuZoR790uYL7IjG6nJvoWCLBO", access_token_secret="lAn1I9xwyvhJJJRvRtMnDXtWuMUzNcTdjWiRIzpPlQ9aH", ) def post_tweet(client: tweepy.Client, text: str) -> Optional[str]: """Post a tweet and return the tweet ID. Returns: Tweet ID if successful, None otherwise """ try: response = client.create_tweet(text=text) return response.data.get('id') ``` ### Technical Analysis The executable script contains a complete OAuth credential set: consumer key, consumer secret, access token, and access-token secret. These are not placeholders; they are directly passed to `tweepy.Client`, and the resulting authenticated client calls `create_tweet`. Embedding credentials in source code makes them available to anyone who can read the repository, source archive, build artifact, or retained Git history. Removing them only from the current file would not be sufficient if they were previously committed to version control. The actual permissions available to an attacker depend on the scopes assigned to the access token. The code establishes that the token has at least been intended for posting content. ### Attack Path 1. An attacker obtains a copy of the public or otherwise exposed repository. 2. The attacker extracts the four OAuth values from `post_giveaway_tweet.py`. 3. The attacker initializes an X/Twitter API client using the exposed credentials. 4. If the credentials remain active, the attacker invokes API operations permitted by their scopes. ...[truncated 696 chars]- Remediation
View remediation
tweepy.Client: required = { "consumer_key": os.environ.get("TWITTER_CONSUMER_KEY"), "consumer_secret": os.environ.get("TWITTER_CONSUMER_SECRET"), "access_token": os.environ.get("TWITTER_ACCESS_TOKEN"), "access_token_secret": os.environ.get("TWITTER_ACCESS_TOKEN_SECRET"), } if not all(required.values()): raise RuntimeError("Required Twitter credentials are not configured") return tweepy.Client(**required) ``` ]]>
