Skip to content

Security ​

Security considerations and best practices for the Gradescope Submitter.

Credential Protection ​

Server-Side Only ​

Gradescope credentials (TOKEN and COOKIE) are:

  • Stored only in .env file on server
  • Never sent to the browser
  • Never logged in production
  • Never committed to version control

Environment Variables ​

env
# These stay on the server
TOKEN=your-gradescope-authenticity-token
COOKIE=your-gradescope-session-cookie
SECRET=your-signing-secret

.gitignore ​

The .env file is excluded from version control:

gitignore
.env
*.pem
keys/

LTI Security ​

JWT Validation ​

All LTI launches are validated:

  1. Signature verification — JWT signed by D2L
  2. Issuer check — Must match D2L's issuer URL
  3. Audience check — Must match our client ID
  4. Expiration check — Token must not be expired
  5. Nonce validation — Prevents replay attacks

State Tokens ​

State tokens in the auth flow:

  • Signed with HMAC-SHA256
  • Include expiration timestamp
  • Single-use (should be invalidated)
javascript
const state = jwt.sign(
  { email, asgId, exp: Date.now() + 300000 },
  process.env.SECRET
);

HTTPS Requirements ​

Why HTTPS? ​

  • D2L requirement — Iframes must load over HTTPS
  • Data protection — Encrypts code and credentials in transit
  • Browser policies — Modern browsers block mixed content

Certificate Management ​

  • Use Let's Encrypt for free certificates
  • Auto-renew before expiration
  • Store certificates securely

Input Validation ​

Server-Side Validation ​

All inputs are validated before processing:

javascript
app.post('/submit', (req, res) => {
  const { code, asg_id } = req.body;
  
  if (!code || typeof code !== 'string') {
    return res.status(400).json({ error: 'Invalid code' });
  }
  
  if (!asg_id || !/^\d+$/.test(asg_id)) {
    return res.status(400).json({ error: 'Invalid assignment ID' });
  }
  
  // ... proceed with validated data
});

Sanitization ​

  • Assignment IDs: Must be numeric
  • File names: Restricted to safe characters
  • Code: Passed as-is to Gradescope (their autograder handles execution)

Code Execution Safety ​

Browser Sandbox ​

Pyodide runs in the browser's WebAssembly sandbox:

  • No file system access — Can't read/write local files
  • No network access — Can't make HTTP requests
  • No system calls — Can't execute shell commands
  • Memory limited — Browser enforces limits

What Students Can't Do ​

python
# These will fail in Pyodide:
import os
os.system('rm -rf /')  # No system access

import requests
requests.get('http://evil.com')  # No network

open('/etc/passwd', 'r')  # No file system

Session Security ​

In-Memory Sessions ​

Student sessions are stored in memory:

  • Lost on server restart
  • No persistent storage vulnerabilities
  • Automatic cleanup

Session Isolation ​

Each student's credentials are separate:

javascript
const sessions = new Map();

function storeSession(userId, credentials) {
  sessions.set(userId, credentials);
}

function getSession(userId) {
  return sessions.get(userId);
}

Rate Limiting ​

javascript
const rateLimit = require('express-rate-limit');

const submitLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 10, // 10 submissions per minute
  message: { error: 'Too many submissions, please wait' }
});

app.use('/submit', submitLimiter);

Why Rate Limit? ​

  • Prevent abuse
  • Protect Gradescope API
  • Ensure fair access

Error Handling ​

Don't Expose Internals ​

javascript
// Bad - exposes internal details
res.status(500).json({ error: err.stack });

// Good - generic message
res.status(500).json({ error: 'Submission failed' });

Log Securely ​

javascript
// Don't log credentials
console.log('Submitting for user:', email);
// NOT: console.log('Cookie:', cookie);

Security Checklist ​

Deployment ​

  • [ ] HTTPS enabled
  • [ ] .env not in version control
  • [ ] Strong SECRET value
  • [ ] Credentials rotated regularly
  • [ ] Rate limiting enabled
  • [ ] Error messages don't expose internals

Code Review ​

  • [ ] No hardcoded credentials
  • [ ] Input validation on all endpoints
  • [ ] Proper error handling
  • [ ] No sensitive data in logs

Monitoring ​

  • [ ] Log failed authentication attempts
  • [ ] Monitor for unusual submission patterns
  • [ ] Alert on repeated errors

Vulnerability Reporting ​

If you discover a security vulnerability:

  1. Do not open a public issue
  2. Email the maintainers directly
  3. Provide details and reproduction steps
  4. Allow time for a fix before disclosure

Released under the MIT License.