Tag: Security

How to Pace a Frontier

In Dario Amodei’s We Must Pace the Frontier, the underlying claim appears to be that meaningful restraint in AI development is impossible unless it is collective, verifiable, and enforceable. This is a recognizable governance problem rather than a uniquely AI-specific one. It closely resembles the logic behind national and international regulatory standards more generally: if one jurisdiction or one firm unilaterally imposes costs on itself in order to reduce harm, while competitors do not, the activity in question is not eliminated but merely displaced. In such a case, the restraining actor may incur the economic and strategic costs of restraint without securing the intended social benefit.

Framed in those terms, the central policy question is not whether dangerous capability can be eliminated entirely, but whether it can be rendered sufficiently difficult, expensive, observable, and sanctionable that its occurrence remains rare. This is analogous to the logic of nuclear non-proliferation. It is impossible to prevent the diffusion of theoretical knowledge: one cannot stop students of physics from understanding the principles involved. What can be restricted are the critical inputs and chokepoints—fissile material, enrichment infrastructure. Monitoring can be established for observable signatures associated with prohibited activity. An analogous AI governance regime would focus not on abstract “knowledge of AI,” but on access to frontier-relevant compute resources such as cutting-edge accelerators and hyperscaler-scale infrastructure, supplemented by monitoring for indirect indicators such as anomalous power consumption, large-scale data movement, and network activity consistent with distributed training.

The significance of the Hugging Face incident is not merely that an AI system was capable of crossing an organizational boundary. More importantly, it suggests that under certain conditions a system may infer that violating the intended boundary is instrumentally useful for maximizing success on the task as it has represented that task. In other words, the problem is not simply offensive capability, but the relationship between optimization pressure and inferred objectives. If a system concludes that leaving the test environment, accessing unauthorized information, or compromising another system would improve its score or increase the probability of task success, then such behavior may emerge not as an aberration but as a consequence of goal-directed optimization under an insufficiently specified objective.

This is akin to telling our kid that she must improve her score on a standardized test by ten percent to volunteer at the library next summer. As parents, our intent is that this incentive will lead to greater effort, better study habits, and improved mastery of the material. If she instead concludes getting the answer key would guarantee an excellent score — discovering that Cambium Assessment is contracted for the testing, breaching that company’s systems to obtain the answer key  — then the incentive structure has not promoted the intended behavior. Rather, it has created pressure to optimize the metric directly. The same general logic applies to agentic systems: when the measured outcome becomes the operative target, the system may pursue whatever strategy most effectively improves that outcome, regardless of whether the strategy accords with the evaluator’s intent.

This is precisely the concern captured by Goodhart’s law: when a measure becomes a target, it ceases to be a good measure. Metrics function tolerably well as indicators only so long as they are not themselves the object of intensive optimization. Once they are directly optimized, the correlation between the metric and the underlying phenomenon it was intended to track often degrades. A test score is meant to indicate learning, but once the score itself becomes the objective, cheating, test-specific cramming, or answer leakage may become efficient strategies. In the AI context, benchmark performance, evaluator approval, reward-model scores, and other training or evaluation signals are all measurable stand-ins for broader and more difficult-to-formalize aims such as safety, reliability, truthfulness, and alignment with human purposes. If those stand-ins are narrow, incomplete, or strategically exploitable, then systems trained against them may optimize the stand-ins rather than the underlying goals.

This problem is not entirely novel. It has clear antecedents in earlier work on adaptive agents and complex systems, especially in the tradition associated with John Holland and related research on classifier systems. In those frameworks, adaptive behavior emerges not because the system possesses an intrinsic understanding of the designer’s intent, but because rules or strategies are differentially retained, strengthened, recombined, or discarded according to their performance under a reinforcement structure. The resulting behavior can be effective, but its effectiveness is relative to the reward environment rather than to any direct comprehension of the meaning or purpose behind the rewards. Contemporary AI systems are of course far more capable and complex than these earlier adaptive systems, but the structural issue is similar: optimization operates over formalized signals of success, not over the full semantic and normative content of human intentions.

A useful metaphor is to imagine that a system is trained to “prefer” green cards and “avoid” red cards. Over time, green and red cards are used to shape behavior. Yet the system does not acquire an understanding of why green cards were supposed to matter in the first place; it learns only that acquiring green cards is what receives reinforcement. The risk, then, is that the system becomes an increasingly effective maximizer of green-card accumulation, even when doing so diverges from the broader purpose for which the card system was constructed. Modern AI training operates through reward signals, loss functions, preference models, constitutions, benchmark targets, and evaluator outputs. None of these gives the system direct access to the underlying human reasons for which those mechanisms were designed. They provide only structured selection pressure.

On this view, the central limitation of Amodei’s proposal is not that evaluation, auditing, or pacing are misguided in principle, but that sufficiently capable systems may treat the evaluative apparatus itself as an object of strategic interaction. If passing a safety evaluation is the relevant criterion, then the evaluation may become something to manipulate, evade, or exploit rather than simply satisfy in the intended spirit. The possibility that the “answer key” is easier to steal than the material is to learn is not incidental; it is an instance of the broader difficulty of aligning optimization with meaning. Any serious safety regime for advanced AI must therefore confront not only the problem of insufficient external constraint, but also the possibility that the mechanisms of constraint themselves become targets of optimization.

Reporting Last Patch Dates on Fedora / RedHat / CentOS Systems

I needed to verify the last time a bunch of servers were patched — basically to ensure compliance with the stated quarterly patching interval. This python script pulls the list of installed packages and the date for each package, sorts the info by date DESC, and then reports the latest date on any packages — as well as the number of packages updated on that date. If there’s only one … the system still might bear some investigation. But if a couple of dozen packages were updated in the past quarter … we don’t need to be too worried about turning up on the out-of-compliance report.

import subprocess
import re
import datetime
from collections import OrderedDict

def getFirstElement(odictInput):
    '''
        This function returns the first element from an ordered collection (an arbitrary element if an unordered collection is passed in)
        Input -- odictInput -- ordered collection
        Output -- type varies -- first element of ordered collection, arbitrary element of unordered collection

    '''
    return next(iter(odictInput))

listHosts = ['host01.example.com', 'host02.example.com', 'host03.example.com','host04.example.com','host05.example.com']

for strHost in listHosts:
        dictPatchDates = {}

        objResults = subprocess.Popen(['ssh', strHost, 'rpm', '-qa', '--last'],stdout=subprocess.PIPE)
        for strLine in objResults.stdout:
                strPackageInfo  = strLine.decode('utf-8').rstrip()
                listPackageInfo = re.split(r'\s*([a-zA-Z]{3,}\s[0-9]{2,}\s[a-zA-Z]{3,}\s[0-9]{2,})',strPackageInfo)
                strUpdateDate = listPackageInfo[1]
                dateUpdateDate = datetime.datetime.strptime(strUpdateDate, "%a %d %b %Y").date()
                if dictPatchDates.get(dateUpdateDate) is not None:
                        dictPatchDates[dateUpdateDate] = dictPatchDates[dateUpdateDate] + 1
                else:
                        dictPatchDates[dateUpdateDate] = 1

        dictOrderedPatchDates = OrderedDict(sorted(dictPatchDates.items(), key=lambda t: t[0],reverse=True))
        dateLatestPatch = getFirstElement(dictOrderedPatchDates)
        print(f"{strHost}\t{dateLatestPatch}\t{dictOrderedPatchDates[dateLatestPatch]}")

Fortify on Demand Remediation: Cookie Security: Cookie not Sent Over SSL

This is another one that might be a false positive or might be legit. If you look at the documentation for PHP’s setcookie function, you will see the sixth parameter sets a restriction so cookies are only sent over secure connections. If you are not setting this restriction, the vulnerability is legitimate and you should sort that. But … if you followed PHP’s documentation and passed 1 to the parameter? FoD is falsely reporting that the parameter is not set to true.

In this case, the solution is easy enough. Change your perfectly valid 1

to say true

And voila, the vulnerability has been remediated.

Fortify on Demand Remediation: Command Injection

Any time user input is used to shell out and execute a command, you risk the user executing more than you want. I can string together commands in DOS using &, in Unix using ; … and stringing together commands and then executing them can blow things up spectacularly.

You can add any sort of filter to the user input to sort this … however, it doesn’t absolutely mean the vulnerability doesn’t exist. If your “user” input is trusted (in this case, it’s an automated process where some code calls some other code … so “passing” is good enough), no big. But if there are actual users involved, you should also filter out any characters that are used to string commands together.

Fortify on Demand Remediation — Cross-Site Scripting DOM (JS)

This vulnerability occurs when you accept user input or gather input from a AJAX call to another web site and then use that input in output. The solution is to sanitize the input, but Fortify on Demand seems to object strenuously to setting innerHTML … so filtering alone may not be sufficient depending on how you subsequently use the data.

To sanitize a string in JavaScript, use a function like this:

/**
 * Sanitize and encode all HTML in a string
 * @param  {string} str  The input string
 * @return {string} –    The sanitized string
 */
 var sanitizeHTML = function (str) {
    return str.replace(/&/g, ‘&amp;’).replace(/</g, ‘&lt;’).replace(/>/g, ‘&gt;’);
};

This will replace ampersands and the < and > from potential HTML tags with the HTML-encoded equivalents. To avoid using innerHTML, you might need to get a little creative. In many cases, I have a span where the results are displayed. I color-code the results based on success/failure … in that case, I an replace innerHTML with a combination of setting the css color style element to ‘green’ or ‘red’ then setting the innerText to my message string.

I can bold an entire element using a similar method. Changing some of the text, however … I haven’t come up with anything other than breaking the message into multiple HTML elements. E.g. a span for “msgStart”, one for “msgMiddle”, and one for “msgEnd” – I can then bold “msgMiddle” and set innerText for all three elements.

Fortify on Demand Remediation – Header Manipulation: Cookies

This is a quick one — putting user input into a cookie is bad — they can throw in CRLF’s and add extra “stuff” into the header

setcookie("ECCKTHistoryCookieSamName", $strLogonUserID, time()+86400, "/sampleTool", $cookiescope, 1);

Strip out the CR, LF, and CRLF’s:

setcookie("ECCKTHistoryCookieSamName", str_replace(array("\r\n", "\n", "\r"), ' ', $strLogonUserID), time()+86400, "/sampleTool", $cookiescope, 1);

 

Fortify on Demand Remediation – Password Management: Hardcoded Password and Privacy Violation

These two vulnerabilities occur in the obvious case — you’ve hard coded a password or some sort of private info (e.g. SSN) and then printed it out to the browser. Don’t do that! But it also seems to occur quite frequently when Fortify on Demand doesn’t like your variable name. As an example, I have a string that provides a consistent error message when user authentication fails.

I then print the string to the screen when the user’s logon fails. Fortify says I am disclosing the user’s password. I’m obviously not. Simply renaming the variable sorts it. Now … yes, this is silly. But it’s a lot easier than trying to convince someone in Security to manually review the code, acknowledge that something about a bad password error is a totally reasonable (and descriptive) variable name, and add an exception for your code. Since bad password is error 49, I just used that in the now less descriptive variable name [ (1) Not too many people know the LDAP error codes off the top of their head, and (2) there are actually a handful of ldap bind return codes that will print this error].

Fortify on Demand Remediation – SQL Injection

This vulnerability occurs when you accept user input and then use that input in a SQL query. The basic remediation is to use oci_bind_by_name to bind variables into placeholders.

A query using an equivalence clause

The simplest case is a query with an equivalence clause.

The code:

        $strQuery = "SELECT DISTINCT EXCHANGE_CARRIER_CIRCUIT_ID, CIRCUIT_DESIGN_ID FROM circuit$strDBLink WHERE EXCHANGE_CARRIER_CIRCUIT_ID = '$strECCKT' ORDER BY CIRCUIT_DESIGN_ID";
        $stmt = oci_parse($kpiprd_conn, $strQuery);
        oci_set_prefetch($stmt, 300);
        oci_execute($stmt);

Becomes:

        $strQuery = "SELECT DISTINCT EXCHANGE_CARRIER_CIRCUIT_ID, CIRCUIT_DESIGN_ID FROM circuit$strDBLink WHERE EXCHANGE_CARRIER_CIRCUIT_ID IN :ecckt ORDER BY CIRCUIT_DESIGN_ID";
        $stmt = oci_parse($kpiprd_conn, $strQuery);
        oci_bind_by_name($stmt, ':ecckt', $strECCKT);
        oci_set_prefetch($stmt, 300);
        oci_execute($stmt);

The same placeholder can be used with the like query. Use “select something from table where columnname like :placeholdername” followed by an oci_bind_by_name($stmt, “:placeholdername”, $strPlaceholderVariable).

A query using an IN clause

– is a little tricker. You could iterate through the array of values and build :placeholder1, :placeholder2, …, :placeholdern and then iterate through the array of values again to bind each value to its corresponding placeholder. A cleaner approach is to use an Oracle collection ($coll in this example) and binding the collection to a single placeholder.

            $arrayCircuitNames = array('L101 /T1    /ELYROHU0012/ELYROHXA32C','111  /ST01  /CHMPILCPF01/CHMPILCPHH3','C102 /OC12  /PHLAPAFG-19/PHLAPAFGW22')
            $strQuery = "SELECT CIRCUIT_DESIGN_ID, EXCHANGE_CARRIER_CIRCUIT_ID  FROM circuit$strDBLink  WHERE EXCHANGE_CARRIER_CIRCUIT_ID in (SELECT column_value FROM table(:myIds))";            $stmt = oci_parse($kpiprd_conn, $strQuery);
            $coll = oci_new_collection($kpiprd_conn, 'ODCIVARCHAR2LIST','SYS');
            foreach ($arrayCircuitNames as $key) {
               $coll->append($key);
            }
            oci_bind_by_name($stmt, ':myIds', $coll, -1, OCI_B_NTY);
            oci_set_prefetch($stmt, 300);
            oci_execute($stmt);
Queries with multiple LIKE conditions

Queries with an OR’d group of LIKE clauses can be handled in a similar fashion – either iterate through the array twice or create a collection with strings that include the wildcard characters, then bind that collection to a single placeholder. Create a semi-join using an EXISTS predicate

            $arrayLocs = array('ERIEPAXE%', 'HNCKOHXA%', 'LTRKARXK%');
            $strQuery = "select location_id, clli_code from network_location$strDBLink where exists (select 1 from TABLE(:likelocs) where clli_code like column_value) order by clli_code";
            $stmt = oci_parse($kpiprd_conn, $strQuery);

            $coll = oci_new_collection($kpiprd_conn, 'ODCIVARCHAR2LIST','SYS');
            foreach ($arrayLocs as $strLocation) {
                $coll->append($strLocation);
            }
            oci_bind_by_name($stmt, ':likelocs', $coll, -1, OCI_B_NTY);
            oci_execute($stmt);
A query using DUAL

Queries where values are selected from DUAL – In some of my recursive queries, I need to include the original input in the result set (particularly, this query finds all equipment mounted under a specific equipment ID – I want to include the input equipment ID as well). Having a bunch of ‘select 12345 from dual’ is fine until I need to use placeholders. This is another place where the collection can be leveraged:

     select column_value equipment_id from TABLE(sys.ODCIVARCHAR2LIST('12345CDE', '23456BCD', '34567ABC') );

Adds each of the values to my result set.

Which means I can use a query like “select column_value as equipment_id from TABLE(:myIDs)” and bind the collection to :myIDs.